Loading core/java/android/os/ITradeInMode.aidl +33 −0 Original line number Diff line number Diff line Loading @@ -59,4 +59,37 @@ interface ITradeInMode { * ENTER_TRADE_IN_MODE permission is required. */ boolean enterEvaluationMode(); /** * Schedules a wipe to trigger SUW for trade-in mode testing. A reboot is * required. After this, startTesting() can be called. * * ENTER_TRADE_IN_MODE permission is required and ro.debuggable must be 1. */ void scheduleWipeForTesting(); /** * Enables testing. This only takes effect after the next reboot, and is * only allowed in ro.debuggable builds. On the following boot, normal * adbd will be disabled and trade-in mode adbd will be enabled instead. * * ENTER_TRADE_IN_MODE permission is required and ro.debuggable must be 1. */ void startTesting(); /** * Disables testing. This disables trade-in mode and removes any scheduled * trade-in mode wipe. * * ENTER_TRADE_IN_MODE permission is required, ro.debuggable must be 1, and * startTesting() must have been called. */ void stopTesting(); /** * Returns whether the device is testing trade-in mode. * * ENTER_TRADE_IN_MODE permission is required and ro.debuggable must be 1. */ boolean isTesting(); } data/etc/privapp-permissions-platform.xml +1 −0 Original line number Diff line number Diff line Loading @@ -259,6 +259,7 @@ applications that come with the platform <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/> <permission name="android.permission.ACCESS_LOWPAN_STATE"/> <permission name="android.permission.BACKUP"/> <permission name="android.permission.ENTER_TRADE_IN_MODE"/> <!-- Needed for GMSCore Location API test only --> <permission name="android.permission.LOCATION_BYPASS"/> <!-- Needed for test only --> Loading packages/Shell/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -1015,6 +1015,9 @@ <uses-permission android:name="android.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE" /> <uses-permission android:name="android.permission.READ_COLOR_ZONES" /> <!-- Permission required for trade-in mode testing --> <uses-permission android:name="android.permission.ENTER_TRADE_IN_MODE" /> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" Loading services/core/java/com/android/server/TradeInModeService.java +104 −11 Original line number Diff line number Diff line Loading @@ -41,12 +41,15 @@ import android.util.Slog; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; public final class TradeInModeService extends SystemService { private static final String TAG = "TradeInModeService"; private static final String TIM_PROP = "persist.adb.tradeinmode"; private static final String TIM_TEST_PROP = "persist.adb.test_tradeinmode"; private static final int TIM_STATE_UNSET = 0; Loading Loading @@ -108,6 +111,10 @@ public final class TradeInModeService extends SystemService { // setup completion observer. if (isDeviceSetup()) { stopTradeInMode(); } else if (isDebuggable() && !isForceEnabledForTesting()) { // The device was made debuggable after entering TIM. This // can happen while flashing. For convenience, leave test mode. leaveTestMode(); } else { watchForSetupCompletion(); watchForNetworkChange(); Loading Loading @@ -171,12 +178,7 @@ public final class TradeInModeService extends SystemService { Slog.e(TAG, "Cannot enter evaluation mode, FRP lock is present."); return false; } try (FileWriter fw = new FileWriter(WIPE_INDICATOR_FILE, StandardCharsets.US_ASCII)) { fw.write("0"); } catch (IOException e) { Slog.e(TAG, "Failed to write " + WIPE_INDICATOR_FILE, e); if (!scheduleTradeInModeWipe()) { return false; } Loading @@ -189,7 +191,7 @@ public final class TradeInModeService extends SystemService { } SystemProperties.set(TIM_PROP, Integer.toString(TIM_STATE_EVALUATION_MODE)); SystemProperties.set("ctl.restart", "adbd"); restartAdbd(); return true; } Loading @@ -200,6 +202,55 @@ public final class TradeInModeService extends SystemService { "Cannot test for trade-in evaluation mode allowed"); return !isFrpActive(); } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public void scheduleWipeForTesting() { enforceTestingPermissions(); scheduleTradeInModeWipe(); } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public void startTesting() { enforceTestingPermissions(); enterTestMode(); } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public void stopTesting() { enforceTestingPermissions(); if (!isForceEnabledForTesting()) { throw new IllegalStateException("testing must have been started"); } final long callingId = Binder.clearCallingIdentity(); try { leaveTestMode(); } finally { Binder.restoreCallingIdentity(callingId); } } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public boolean isTesting() { enforceTestingPermissions(); return isForceEnabledForTesting(); } private void enforceTestingPermissions() { mContext.enforceCallingOrSelfPermission("android.permission.ENTER_TRADE_IN_MODE", "Caller must have ENTER_TRADE_IN_MODE permission"); if (!isDebuggable()) { throw new SecurityException("ro.debuggable must be set to 1"); } } } private void startTradeInMode() { Loading @@ -207,8 +258,7 @@ public final class TradeInModeService extends SystemService { SystemProperties.set(TIM_PROP, Integer.toString(TIM_STATE_FOYER)); final ContentResolver cr = mContext.getContentResolver(); Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1); setAdbEnabled(true); watchForSetupCompletion(); watchForNetworkChange(); Loading @@ -223,8 +273,51 @@ public final class TradeInModeService extends SystemService { removeNetworkWatch(); removeAccountsWatch(); if (isForceEnabledForTesting()) { // If testing in a debug build, we need to re-enable ADB. restartAdbd(); } else { // Otherwise, ADB must not be enabled. setAdbEnabled(false); } } private void enterTestMode() { SystemProperties.set(TIM_TEST_PROP, "1"); } private void leaveTestMode() { if (getTradeInModeState() == TIM_STATE_FOYER) { stopTradeInMode(); } SystemProperties.set(TIM_TEST_PROP, ""); SystemProperties.set(TIM_PROP, ""); try { Files.deleteIfExists(Paths.get(WIPE_INDICATOR_FILE)); } catch (IOException e) { Slog.e(TAG, "Failed to remove wipe indicator", e); } } private boolean scheduleTradeInModeWipe() { try (FileWriter fw = new FileWriter(WIPE_INDICATOR_FILE, StandardCharsets.US_ASCII)) { fw.write("0"); } catch (IOException e) { Slog.e(TAG, "Failed to write " + WIPE_INDICATOR_FILE, e); return false; } return true; } private void restartAdbd() { SystemProperties.set("ctl.restart", "adbd"); } private void setAdbEnabled(boolean enabled) { final ContentResolver cr = mContext.getContentResolver(); Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 0); Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, enabled ? 1 : 0); } private int getTradeInModeState() { Loading @@ -236,7 +329,7 @@ public final class TradeInModeService extends SystemService { } private boolean isForceEnabledForTesting() { return SystemProperties.getInt("persist.adb.test_tradeinmode", 0) == 1; return isDebuggable() && SystemProperties.getInt(TIM_TEST_PROP, 0) == 1; } private boolean isAdbEnabled() { Loading Loading
core/java/android/os/ITradeInMode.aidl +33 −0 Original line number Diff line number Diff line Loading @@ -59,4 +59,37 @@ interface ITradeInMode { * ENTER_TRADE_IN_MODE permission is required. */ boolean enterEvaluationMode(); /** * Schedules a wipe to trigger SUW for trade-in mode testing. A reboot is * required. After this, startTesting() can be called. * * ENTER_TRADE_IN_MODE permission is required and ro.debuggable must be 1. */ void scheduleWipeForTesting(); /** * Enables testing. This only takes effect after the next reboot, and is * only allowed in ro.debuggable builds. On the following boot, normal * adbd will be disabled and trade-in mode adbd will be enabled instead. * * ENTER_TRADE_IN_MODE permission is required and ro.debuggable must be 1. */ void startTesting(); /** * Disables testing. This disables trade-in mode and removes any scheduled * trade-in mode wipe. * * ENTER_TRADE_IN_MODE permission is required, ro.debuggable must be 1, and * startTesting() must have been called. */ void stopTesting(); /** * Returns whether the device is testing trade-in mode. * * ENTER_TRADE_IN_MODE permission is required and ro.debuggable must be 1. */ boolean isTesting(); }
data/etc/privapp-permissions-platform.xml +1 −0 Original line number Diff line number Diff line Loading @@ -259,6 +259,7 @@ applications that come with the platform <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/> <permission name="android.permission.ACCESS_LOWPAN_STATE"/> <permission name="android.permission.BACKUP"/> <permission name="android.permission.ENTER_TRADE_IN_MODE"/> <!-- Needed for GMSCore Location API test only --> <permission name="android.permission.LOCATION_BYPASS"/> <!-- Needed for test only --> Loading
packages/Shell/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -1015,6 +1015,9 @@ <uses-permission android:name="android.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE" /> <uses-permission android:name="android.permission.READ_COLOR_ZONES" /> <!-- Permission required for trade-in mode testing --> <uses-permission android:name="android.permission.ENTER_TRADE_IN_MODE" /> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" Loading
services/core/java/com/android/server/TradeInModeService.java +104 −11 Original line number Diff line number Diff line Loading @@ -41,12 +41,15 @@ import android.util.Slog; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; public final class TradeInModeService extends SystemService { private static final String TAG = "TradeInModeService"; private static final String TIM_PROP = "persist.adb.tradeinmode"; private static final String TIM_TEST_PROP = "persist.adb.test_tradeinmode"; private static final int TIM_STATE_UNSET = 0; Loading Loading @@ -108,6 +111,10 @@ public final class TradeInModeService extends SystemService { // setup completion observer. if (isDeviceSetup()) { stopTradeInMode(); } else if (isDebuggable() && !isForceEnabledForTesting()) { // The device was made debuggable after entering TIM. This // can happen while flashing. For convenience, leave test mode. leaveTestMode(); } else { watchForSetupCompletion(); watchForNetworkChange(); Loading Loading @@ -171,12 +178,7 @@ public final class TradeInModeService extends SystemService { Slog.e(TAG, "Cannot enter evaluation mode, FRP lock is present."); return false; } try (FileWriter fw = new FileWriter(WIPE_INDICATOR_FILE, StandardCharsets.US_ASCII)) { fw.write("0"); } catch (IOException e) { Slog.e(TAG, "Failed to write " + WIPE_INDICATOR_FILE, e); if (!scheduleTradeInModeWipe()) { return false; } Loading @@ -189,7 +191,7 @@ public final class TradeInModeService extends SystemService { } SystemProperties.set(TIM_PROP, Integer.toString(TIM_STATE_EVALUATION_MODE)); SystemProperties.set("ctl.restart", "adbd"); restartAdbd(); return true; } Loading @@ -200,6 +202,55 @@ public final class TradeInModeService extends SystemService { "Cannot test for trade-in evaluation mode allowed"); return !isFrpActive(); } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public void scheduleWipeForTesting() { enforceTestingPermissions(); scheduleTradeInModeWipe(); } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public void startTesting() { enforceTestingPermissions(); enterTestMode(); } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public void stopTesting() { enforceTestingPermissions(); if (!isForceEnabledForTesting()) { throw new IllegalStateException("testing must have been started"); } final long callingId = Binder.clearCallingIdentity(); try { leaveTestMode(); } finally { Binder.restoreCallingIdentity(callingId); } } @Override @RequiresPermission(android.Manifest.permission.ENTER_TRADE_IN_MODE) public boolean isTesting() { enforceTestingPermissions(); return isForceEnabledForTesting(); } private void enforceTestingPermissions() { mContext.enforceCallingOrSelfPermission("android.permission.ENTER_TRADE_IN_MODE", "Caller must have ENTER_TRADE_IN_MODE permission"); if (!isDebuggable()) { throw new SecurityException("ro.debuggable must be set to 1"); } } } private void startTradeInMode() { Loading @@ -207,8 +258,7 @@ public final class TradeInModeService extends SystemService { SystemProperties.set(TIM_PROP, Integer.toString(TIM_STATE_FOYER)); final ContentResolver cr = mContext.getContentResolver(); Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1); setAdbEnabled(true); watchForSetupCompletion(); watchForNetworkChange(); Loading @@ -223,8 +273,51 @@ public final class TradeInModeService extends SystemService { removeNetworkWatch(); removeAccountsWatch(); if (isForceEnabledForTesting()) { // If testing in a debug build, we need to re-enable ADB. restartAdbd(); } else { // Otherwise, ADB must not be enabled. setAdbEnabled(false); } } private void enterTestMode() { SystemProperties.set(TIM_TEST_PROP, "1"); } private void leaveTestMode() { if (getTradeInModeState() == TIM_STATE_FOYER) { stopTradeInMode(); } SystemProperties.set(TIM_TEST_PROP, ""); SystemProperties.set(TIM_PROP, ""); try { Files.deleteIfExists(Paths.get(WIPE_INDICATOR_FILE)); } catch (IOException e) { Slog.e(TAG, "Failed to remove wipe indicator", e); } } private boolean scheduleTradeInModeWipe() { try (FileWriter fw = new FileWriter(WIPE_INDICATOR_FILE, StandardCharsets.US_ASCII)) { fw.write("0"); } catch (IOException e) { Slog.e(TAG, "Failed to write " + WIPE_INDICATOR_FILE, e); return false; } return true; } private void restartAdbd() { SystemProperties.set("ctl.restart", "adbd"); } private void setAdbEnabled(boolean enabled) { final ContentResolver cr = mContext.getContentResolver(); Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 0); Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, enabled ? 1 : 0); } private int getTradeInModeState() { Loading @@ -236,7 +329,7 @@ public final class TradeInModeService extends SystemService { } private boolean isForceEnabledForTesting() { return SystemProperties.getInt("persist.adb.test_tradeinmode", 0) == 1; return isDebuggable() && SystemProperties.getInt(TIM_TEST_PROP, 0) == 1; } private boolean isAdbEnabled() { Loading