blob: 2b27e50d2ab8a7269e1e1ae64bf6bb15f634497f [file] [log] [blame] [edit]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <regex>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#if defined(__ANDROID__)
#include <log/log_properties.h>
#include "selinux/android.h"
#endif
#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
#include <com_android_tradeinmode_flags.h>
#endif
static bool in_tradeinmode = false;
static constexpr char kTradeInModeProp[] = "persist.adb.tradeinmode";
static constexpr int TIM_DISABLED = -1;
static constexpr int TIM_UNSET = 0;
static constexpr int TIM_FOYER = 1;
static constexpr int TIM_EVALUATION_MODE = 2;
bool should_enter_tradeinmode() {
#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
if (!com_android_tradeinmode_flags_enable_trade_in_mode()) {
return false;
}
return android::base::GetIntProperty(kTradeInModeProp, TIM_UNSET) == TIM_FOYER;
#else
return false;
#endif
}
void enter_tradeinmode(const char* seclabel) {
#if defined(__ANDROID__)
if (selinux_android_setcon(seclabel) < 0) {
PLOG(ERROR) << "Could not set SELinux context";
// Flag TIM as failed so we don't enter a restart loop.
android::base::SetProperty(kTradeInModeProp, std::to_string(TIM_DISABLED));
_exit(1);
}
// Keep a separate global flag for TIM in case the property changes (for
// example, if it's set while as root for testing).
in_tradeinmode = true;
#endif
}
bool is_in_tradeinmode() {
return in_tradeinmode;
}
bool is_in_tradein_evaluation_mode() {
return android::base::GetIntProperty(kTradeInModeProp, TIM_UNSET) == TIM_EVALUATION_MODE;
}
bool allow_tradeinmode_command(std::string_view name) {
#if defined(__ANDROID__)
// Allow "adb root" from trade-in-mode so that automated testing is possible.
if (__android_log_is_debuggable() && android::base::ConsumePrefix(&name, "root:")) {
return true;
}
#endif
// Allow "shell tradeinmode" with only simple arguments.
std::regex tim_pattern("shell[^:]*:tradeinmode(\\s*|\\s[A-Za-z0-9_\\-\\s]*)");
return std::regex_match(std::string(name), tim_pattern);
}