Merge "profcollect: collect intilization code behavior for camera open events" into main
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 8236783..511c680 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -109,4 +109,5 @@
boolean isWeakEscrowTokenActive(long handle, int userId);
boolean isWeakEscrowTokenValid(long handle, in byte[] token, int userId);
void unlockUserKeyIfUnsecured(int userId);
+ boolean writeRepairModeCredential(int userId);
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index e46b8d7..f4ad487 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -449,6 +449,21 @@
}
/**
+ * Save the current password data to the repair mode file.
+ *
+ * @return true if success or false otherwise.
+ */
+ public boolean writeRepairModeCredential(int userId) {
+ throwIfCalledOnMainThread();
+ try {
+ return getLockSettings().writeRepairModeCredential(userId);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Failed to write repair mode credential", re);
+ return false;
+ }
+ }
+
+ /**
* Check to see if a credential matches the saved one.
* If credential matches, return an opaque attestation that the challenge was verified.
*
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 0734e68..11c220b 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -261,6 +261,8 @@
public float lineEndY = Float.MIN_VALUE;
@Nullable
Animator activationAnimator;
+ @Nullable
+ Animator deactivationAnimator;
}
/**
@@ -667,7 +669,7 @@
*/
private void resetPattern() {
if (mKeepDotActivated && !mPattern.isEmpty()) {
- resetLastActivatedCellProgress();
+ resetPatternCellSize();
}
mPattern.clear();
mPatternPath.reset();
@@ -676,14 +678,20 @@
invalidate();
}
- private void resetLastActivatedCellProgress() {
- final ArrayList<Cell> pattern = mPattern;
- final Cell lastCell = pattern.get(pattern.size() - 1);
- final CellState cellState = mCellStates[lastCell.row][lastCell.column];
- if (cellState.activationAnimator != null) {
- cellState.activationAnimator.cancel();
+ private void resetPatternCellSize() {
+ for (int i = 0; i < mCellStates.length; i++) {
+ for (int j = 0; j < mCellStates[i].length; j++) {
+ CellState cellState = mCellStates[i][j];
+ if (cellState.activationAnimator != null) {
+ cellState.activationAnimator.cancel();
+ }
+ if (cellState.deactivationAnimator != null) {
+ cellState.deactivationAnimator.cancel();
+ }
+ cellState.activationAnimationProgress = 0f;
+ cellState.radius = mDotSize / 2f;
+ }
}
- cellState.activationAnimationProgress = 0f;
}
/**
@@ -819,12 +827,16 @@
!mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
addCellToPattern(fillInGapCell);
if (mKeepDotActivated) {
- startCellDeactivatedAnimation(fillInGapCell);
+ if (mFadePattern) {
+ startCellDeactivatedAnimation(fillInGapCell, /* fillInGap= */ true);
+ } else {
+ startCellActivatedAnimation(fillInGapCell);
+ }
}
}
if (mKeepDotActivated && lastCell != null) {
- startCellDeactivatedAnimation(lastCell);
+ startCellDeactivatedAnimation(lastCell, /* fillInGap= */ false);
}
addCellToPattern(cell);
@@ -872,17 +884,25 @@
}
private void startCellActivatedAnimation(Cell cell) {
- startCellActivationAnimation(cell, CELL_ACTIVATE);
+ startCellActivationAnimation(cell, CELL_ACTIVATE, /* fillInGap= */ false);
}
- private void startCellDeactivatedAnimation(Cell cell) {
- startCellActivationAnimation(cell, CELL_DEACTIVATE);
+ private void startCellDeactivatedAnimation(Cell cell, boolean fillInGap) {
+ startCellActivationAnimation(cell, CELL_DEACTIVATE, /* fillInGap= */ fillInGap);
}
- private void startCellActivationAnimation(Cell cell, int activate) {
+ /**
+ * Start cell animation.
+ * @param cell The cell to be animated.
+ * @param activate Whether the cell is being activated or deactivated.
+ * @param fillInGap Whether the cell is a gap cell, i.e. filled in based on current pattern.
+ */
+ private void startCellActivationAnimation(Cell cell, int activate, boolean fillInGap) {
final CellState cellState = mCellStates[cell.row][cell.column];
- if (cellState.activationAnimator != null) {
+ // When mKeepDotActivated is true, don't cancel the previous animator since it would leave
+ // a dot in an in-between size if the next dot is reached before the animation is finished.
+ if (cellState.activationAnimator != null && !mKeepDotActivated) {
cellState.activationAnimator.cancel();
}
AnimatorSet animatorSet = new AnimatorSet();
@@ -898,24 +918,37 @@
.with(createLineEndAnimation(cellState, startX, startY,
getCenterXForColumn(cell.column), getCenterYForRow(cell.row)));
if (mDotSize != mDotSizeActivated) {
- animatorSetBuilder.with(createDotRadiusAnimation(cellState));
+ animatorSetBuilder.with(createDotRadiusAnimation(cellState, activate, fillInGap));
}
if (mDotColor != mDotActivatedColor) {
- animatorSetBuilder.with(createDotActivationColorAnimation(cellState, activate));
+ animatorSetBuilder.with(
+ createDotActivationColorAnimation(cellState, activate, fillInGap));
}
- animatorSet.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- cellState.activationAnimator = null;
- invalidate();
- }
- });
- cellState.activationAnimator = animatorSet;
+ if (activate == CELL_ACTIVATE) {
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ cellState.activationAnimator = null;
+ invalidate();
+ }
+ });
+ cellState.activationAnimator = animatorSet;
+ } else {
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ cellState.deactivationAnimator = null;
+ invalidate();
+ }
+ });
+ cellState.deactivationAnimator = animatorSet;
+ }
animatorSet.start();
}
- private Animator createDotActivationColorAnimation(CellState cellState, int activate) {
+ private Animator createDotActivationColorAnimation(
+ CellState cellState, int activate, boolean fillInGap) {
ValueAnimator.AnimatorUpdateListener updateListener =
valueAnimator -> {
cellState.activationAnimationProgress =
@@ -934,7 +967,7 @@
deactivateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
AnimatorSet set = new AnimatorSet();
- if (mKeepDotActivated) {
+ if (mKeepDotActivated && !fillInGap) {
set.play(activate == CELL_ACTIVATE ? activateAnimator : deactivateAnimator);
} else {
// 'activate' ignored in this case, do full deactivate -> activate cycle
@@ -977,7 +1010,7 @@
return valueAnimator;
}
- private Animator createDotRadiusAnimation(CellState state) {
+ private Animator createDotRadiusAnimation(CellState state, int activate, boolean fillInGap) {
float defaultRadius = mDotSize / 2f;
float activatedRadius = mDotSizeActivated / 2f;
@@ -998,7 +1031,19 @@
deactivationAnimator.setDuration(DOT_RADIUS_DECREASE_DURATION_MILLIS);
AnimatorSet set = new AnimatorSet();
- set.playSequentially(activationAnimator, deactivationAnimator);
+ if (mKeepDotActivated) {
+ if (mFadePattern) {
+ if (fillInGap) {
+ set.playSequentially(activationAnimator, deactivationAnimator);
+ } else {
+ set.play(activate == CELL_ACTIVATE ? activationAnimator : deactivationAnimator);
+ }
+ } else if (activate == CELL_ACTIVATE) {
+ set.play(activationAnimator);
+ }
+ } else {
+ set.playSequentially(activationAnimator, deactivationAnimator);
+ }
return set;
}
@@ -1176,9 +1221,15 @@
// report pattern detected
if (!mPattern.isEmpty()) {
setPatternInProgress(false);
- cancelLineAnimations();
if (mKeepDotActivated) {
+ // When mKeepDotActivated is true, cancelling dot animations and resetting dot radii
+ // are handled in #resetPattern(), since we want to keep the dots activated until
+ // the pattern are reset.
deactivateLastCell();
+ } else {
+ // When mKeepDotActivated is false, cancelling animations and resetting dot radii
+ // are handled here.
+ cancelLineAnimations();
}
notifyPatternDetected();
// Also clear pattern if fading is enabled
@@ -1198,7 +1249,7 @@
private void deactivateLastCell() {
Cell lastCell = mPattern.get(mPattern.size() - 1);
- startCellDeactivatedAnimation(lastCell);
+ startCellDeactivatedAnimation(lastCell, /* fillInGap= */ false);
}
private void cancelLineAnimations() {
diff --git a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
index b90480a..92a7d8e 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
@@ -68,6 +68,7 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -316,6 +317,40 @@
assertNotEquals(UserHandle.USER_CURRENT_OR_SELF, LockPatternUtils.USER_REPAIR_MODE);
}
+ @Test
+ public void testWriteRepairModeCredential_mainThread() {
+ createTestLockSettings();
+ var context = InstrumentationRegistry.getTargetContext();
+
+ var future = new CompletableFuture<Exception>();
+ context.getMainThreadHandler().post(() -> {
+ try {
+ mLockPatternUtils.writeRepairModeCredential(USER_ID);
+ future.complete(null);
+ } catch (Exception e) {
+ future.complete(e);
+ }
+ });
+
+ var e = future.join();
+ assertThat(e).isNotNull();
+ assertThat(e.getMessage()).contains("should not be called from the main thread");
+ }
+
+ @Test
+ public void testWriteRepairModeCredential() throws Exception {
+ var ils = createTestLockSettings();
+
+ when(ils.writeRepairModeCredential(USER_ID)).thenReturn(false);
+ assertThat(mLockPatternUtils.writeRepairModeCredential(USER_ID)).isFalse();
+
+ when(ils.writeRepairModeCredential(USER_ID)).thenReturn(true);
+ assertThat(mLockPatternUtils.writeRepairModeCredential(USER_ID)).isTrue();
+
+ when(ils.writeRepairModeCredential(USER_ID)).thenThrow(new RemoteException());
+ assertThat(mLockPatternUtils.writeRepairModeCredential(USER_ID)).isFalse();
+ }
+
private TestStrongAuthTracker createStrongAuthTracker() {
final Context context = new ContextWrapper(InstrumentationRegistry.getTargetContext());
return new TestStrongAuthTracker(context, Looper.getMainLooper());
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 2545620..a627a39 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -48,3 +48,6 @@
# SystemConfig
per-file SystemConfig.java = file:/PACKAGE_MANAGER_OWNERS
+
+# CertBlocklister
+per-file Cert*.java = tweek@google.com, brambonne@google.com, prb@google.com, miguelaranda@google.com
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index dfd148d..a4026eb 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -241,12 +241,14 @@
* opportunity to reset any settings depending on our rescue level.
*/
public static void onSettingsProviderPublished(Context context) {
- handleNativeRescuePartyResets();
- ContentResolver contentResolver = context.getContentResolver();
- DeviceConfig.setMonitorCallback(
- contentResolver,
- Executors.newSingleThreadExecutor(),
- new RescuePartyMonitorCallback(context));
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ handleNativeRescuePartyResets();
+ ContentResolver contentResolver = context.getContentResolver();
+ DeviceConfig.setMonitorCallback(
+ contentResolver,
+ Executors.newSingleThreadExecutor(),
+ new RescuePartyMonitorCallback(context));
+ }
}
@@ -256,75 +258,81 @@
* on modules of newer versions.
*/
public static void resetDeviceConfigForPackages(List<String> packageNames) {
- if (packageNames == null) {
- return;
- }
- Set<String> namespacesToReset = new ArraySet<String>();
- Iterator<String> it = packageNames.iterator();
- RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated();
- // Get runtime package to namespace mapping if created.
- if (rescuePartyObserver != null) {
- while (it.hasNext()) {
- String packageName = it.next();
- Set<String> runtimeAffectedNamespaces =
- rescuePartyObserver.getAffectedNamespaceSet(packageName);
- if (runtimeAffectedNamespaces != null) {
- namespacesToReset.addAll(runtimeAffectedNamespaces);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ if (packageNames == null) {
+ return;
+ }
+ Set<String> namespacesToReset = new ArraySet<String>();
+ Iterator<String> it = packageNames.iterator();
+ RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated();
+ // Get runtime package to namespace mapping if created.
+ if (rescuePartyObserver != null) {
+ while (it.hasNext()) {
+ String packageName = it.next();
+ Set<String> runtimeAffectedNamespaces =
+ rescuePartyObserver.getAffectedNamespaceSet(packageName);
+ if (runtimeAffectedNamespaces != null) {
+ namespacesToReset.addAll(runtimeAffectedNamespaces);
+ }
}
}
- }
- // Get preset package to namespace mapping if created.
- Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages(
- packageNames);
- if (presetAffectedNamespaces != null) {
- namespacesToReset.addAll(presetAffectedNamespaces);
- }
+ // Get preset package to namespace mapping if created.
+ Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages(
+ packageNames);
+ if (presetAffectedNamespaces != null) {
+ namespacesToReset.addAll(presetAffectedNamespaces);
+ }
- // Clear flags under the namespaces mapped to these packages.
- // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set.
- Iterator<String> namespaceIt = namespacesToReset.iterator();
- while (namespaceIt.hasNext()) {
- String namespaceToReset = namespaceIt.next();
- Properties properties = new Properties.Builder(namespaceToReset).build();
- try {
- if (!DeviceConfig.setProperties(properties)) {
- logCriticalInfo(Log.ERROR, "Failed to clear properties under "
+ // Clear flags under the namespaces mapped to these packages.
+ // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set.
+ Iterator<String> namespaceIt = namespacesToReset.iterator();
+ while (namespaceIt.hasNext()) {
+ String namespaceToReset = namespaceIt.next();
+ Properties properties = new Properties.Builder(namespaceToReset).build();
+ try {
+ if (!DeviceConfig.setProperties(properties)) {
+ logCriticalInfo(Log.ERROR, "Failed to clear properties under "
+ namespaceToReset
+ ". Running `device_config get_sync_disabled_for_tests` will confirm"
+ " if config-bulk-update is enabled.");
+ }
+ } catch (DeviceConfig.BadConfigException exception) {
+ logCriticalInfo(Log.WARN, "namespace " + namespaceToReset
+ + " is already banned, skip reset.");
}
- } catch (DeviceConfig.BadConfigException exception) {
- logCriticalInfo(Log.WARN, "namespace " + namespaceToReset
- + " is already banned, skip reset.");
}
}
}
private static Set<String> getPresetNamespacesForPackages(List<String> packageNames) {
Set<String> resultSet = new ArraySet<String>();
- try {
- String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION,
- NAMESPACE_TO_PACKAGE_MAPPING_FLAG, "");
- String[] mappingEntries = flagVal.split(",");
- for (int i = 0; i < mappingEntries.length; i++) {
- if (TextUtils.isEmpty(mappingEntries[i])) {
- continue;
- }
- String[] splittedEntry = mappingEntries[i].split(":");
- if (splittedEntry.length != 2) {
- throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]);
- }
- String namespace = splittedEntry[0];
- String packageName = splittedEntry[1];
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ try {
+ String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION,
+ NAMESPACE_TO_PACKAGE_MAPPING_FLAG, "");
+ String[] mappingEntries = flagVal.split(",");
+ for (int i = 0; i < mappingEntries.length; i++) {
+ if (TextUtils.isEmpty(mappingEntries[i])) {
+ continue;
+ }
+ String[] splitEntry = mappingEntries[i].split(":");
+ if (splitEntry.length != 2) {
+ throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]);
+ }
+ String namespace = splitEntry[0];
+ String packageName = splitEntry[1];
- if (packageNames.contains(packageName)) {
- resultSet.add(namespace);
+ if (packageNames.contains(packageName)) {
+ resultSet.add(namespace);
+ }
}
+ } catch (Exception e) {
+ resultSet.clear();
+ Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e);
+ } finally {
+ return resultSet;
}
- } catch (Exception e) {
- resultSet.clear();
- Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e);
- } finally {
+ } else {
return resultSet;
}
}
@@ -342,43 +350,54 @@
}
public void onNamespaceUpdate(@NonNull String updatedNamespace) {
- startObservingPackages(mContext, updatedNamespace);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ startObservingPackages(mContext, updatedNamespace);
+ }
}
public void onDeviceConfigAccess(@NonNull String callingPackage,
@NonNull String namespace) {
- RescuePartyObserver.getInstance(mContext).recordDeviceConfigAccess(
- callingPackage,
- namespace);
+
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ RescuePartyObserver.getInstance(mContext).recordDeviceConfigAccess(
+ callingPackage,
+ namespace);
+ }
}
}
private static void startObservingPackages(Context context, @NonNull String updatedNamespace) {
- RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
- Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet(updatedNamespace);
- if (callingPackages == null) {
- return;
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+ Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet(
+ updatedNamespace);
+ if (callingPackages == null) {
+ return;
+ }
+ List<String> callingPackageList = new ArrayList<>();
+ callingPackageList.addAll(callingPackages);
+ Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
+ + updatedNamespace);
+ PackageWatchdog.getInstance(context).startObservingHealth(
+ rescuePartyObserver,
+ callingPackageList,
+ DEFAULT_OBSERVING_DURATION_MS);
}
- List<String> callingPackageList = new ArrayList<>();
- callingPackageList.addAll(callingPackages);
- Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
- + updatedNamespace);
- PackageWatchdog.getInstance(context).startObservingHealth(
- rescuePartyObserver,
- callingPackageList,
- DEFAULT_OBSERVING_DURATION_MS);
}
private static void handleNativeRescuePartyResets() {
- if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
- String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories();
- for (int i = 0; i < resetNativeCategories.length; i++) {
- // Don't let RescueParty reset the namespace for RescueParty switches.
- if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) {
- continue;
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
+ String[] resetNativeCategories =
+ SettingsToPropertiesMapper.getResetNativeCategories();
+ for (int i = 0; i < resetNativeCategories.length; i++) {
+ // Don't let RescueParty reset the namespace for RescueParty switches.
+ if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) {
+ continue;
+ }
+ DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE,
+ resetNativeCategories[i]);
}
- DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE,
- resetNativeCategories[i]);
}
}
}
@@ -400,6 +419,13 @@
}
}
+ private static int getMaxRescueLevel() {
+ if (!SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
+ return Level.factoryReset();
+ }
+ return Level.reboot();
+ }
+
/**
* Get the rescue level to perform if this is the n-th attempt at mitigating failure.
*
@@ -409,19 +435,30 @@
* @return the rescue level for the n-th mitigation attempt.
*/
private static int getRescueLevel(int mitigationCount, boolean mayPerformReboot) {
- if (mitigationCount == 1) {
- return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
- } else if (mitigationCount == 2) {
- return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES;
- } else if (mitigationCount == 3) {
- return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
- } else if (mitigationCount == 4) {
- return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT);
- } else if (mitigationCount >= 5) {
- return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ if (mitigationCount == 1) {
+ return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
+ } else if (mitigationCount == 2) {
+ return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES;
+ } else if (mitigationCount == 3) {
+ return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
+ } else if (mitigationCount == 4) {
+ return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT);
+ } else if (mitigationCount >= 5) {
+ return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET);
+ } else {
+ Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
+ return LEVEL_NONE;
+ }
} else {
- Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
- return LEVEL_NONE;
+ if (mitigationCount == 1) {
+ return Level.reboot();
+ } else if (mitigationCount >= 2) {
+ return Math.min(getMaxRescueLevel(), Level.factoryReset());
+ } else {
+ Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
+ return LEVEL_NONE;
+ }
}
}
@@ -451,13 +488,13 @@
return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_WARM_REBOOT);
} else if (mitigationCount == 4) {
return Math.min(getMaxRescueLevel(mayPerformReboot),
- RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS);
+ RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS);
} else if (mitigationCount == 5) {
return Math.min(getMaxRescueLevel(mayPerformReboot),
- RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES);
+ RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES);
} else if (mitigationCount == 6) {
return Math.min(getMaxRescueLevel(mayPerformReboot),
- RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS);
+ RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS);
} else if (mitigationCount >= 7) {
return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_FACTORY_RESET);
} else {
@@ -465,6 +502,22 @@
}
}
+ /**
+ * Get the rescue level to perform if this is the n-th attempt at mitigating failure.
+ *
+ * @param mitigationCount the mitigation attempt number (1 = first attempt etc.).
+ * @return the rescue level for the n-th mitigation attempt.
+ */
+ private static @RescueLevels int getRescueLevel(int mitigationCount) {
+ if (mitigationCount == 1) {
+ return Level.reboot();
+ } else if (mitigationCount >= 2) {
+ return Math.min(getMaxRescueLevel(), Level.factoryReset());
+ } else {
+ return Level.none();
+ }
+ }
+
private static void executeRescueLevel(Context context, @Nullable String failedPackage,
int level) {
Slog.w(TAG, "Attempting rescue level " + levelToString(level));
@@ -537,13 +590,22 @@
executeWarmReboot(context, level, failedPackage);
break;
case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
- resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS, level);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS,
+ level);
+ }
break;
case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
- resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES, level);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES,
+ level);
+ }
break;
case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
- resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, level);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS,
+ level);
+ }
break;
case RESCUE_LEVEL_FACTORY_RESET:
// Before the completion of Reboot, if any crash happens then PackageWatchdog
@@ -560,6 +622,12 @@
private static void executeWarmReboot(Context context, int level,
@Nullable String failedPackage) {
+ if (Flags.deprecateFlagsAndSettingsResets()) {
+ if (shouldThrottleReboot()) {
+ return;
+ }
+ }
+
// Request the reboot from a separate thread to avoid deadlock on PackageWatchdog
// when device shutting down.
setRebootProperty(true);
@@ -579,6 +647,11 @@
private static void executeFactoryReset(Context context, int level,
@Nullable String failedPackage) {
+ if (Flags.deprecateFlagsAndSettingsResets()) {
+ if (shouldThrottleReboot()) {
+ return;
+ }
+ }
setFactoryResetProperty(true);
long now = System.currentTimeMillis();
setLastFactoryResetTimeMs(now);
@@ -655,30 +728,32 @@
private static void resetAllSettingsIfNecessary(Context context, int mode,
int level) throws Exception {
- // No need to reset Settings again if they are already reset in the current level once.
- if (getMaxRescueLevelAttempted() >= level) {
- return;
- }
- setMaxRescueLevelAttempted(level);
- // Try our best to reset all settings possible, and once finished
- // rethrow any exception that we encountered
- Exception res = null;
- final ContentResolver resolver = context.getContentResolver();
- try {
- Settings.Global.resetToDefaultsAsUser(resolver, null, mode,
- UserHandle.SYSTEM.getIdentifier());
- } catch (Exception e) {
- res = new RuntimeException("Failed to reset global settings", e);
- }
- for (int userId : getAllUserIds()) {
- try {
- Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
- } catch (Exception e) {
- res = new RuntimeException("Failed to reset secure settings for " + userId, e);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ // No need to reset Settings again if they are already reset in the current level once.
+ if (getMaxRescueLevelAttempted() >= level) {
+ return;
}
- }
- if (res != null) {
- throw res;
+ setMaxRescueLevelAttempted(level);
+ // Try our best to reset all settings possible, and once finished
+ // rethrow any exception that we encountered
+ Exception res = null;
+ final ContentResolver resolver = context.getContentResolver();
+ try {
+ Settings.Global.resetToDefaultsAsUser(resolver, null, mode,
+ UserHandle.SYSTEM.getIdentifier());
+ } catch (Exception e) {
+ res = new RuntimeException("Failed to reset global settings", e);
+ }
+ for (int userId : getAllUserIds()) {
+ try {
+ Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
+ } catch (Exception e) {
+ res = new RuntimeException("Failed to reset secure settings for " + userId, e);
+ }
+ }
+ if (res != null) {
+ throw res;
+ }
}
}
@@ -731,11 +806,15 @@
if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
|| failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) {
if (Flags.recoverabilityDetection()) {
- return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
- mayPerformReboot(failedPackage), failedPackage));
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+ mayPerformReboot(failedPackage), failedPackage));
+ } else {
+ return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount));
+ }
} else {
return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
- mayPerformReboot(failedPackage)));
+ mayPerformReboot(failedPackage)));
}
} else {
return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
@@ -750,10 +829,17 @@
}
if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
|| failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
- final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount,
- mayPerformReboot(failedPackage), failedPackage)
- : getRescueLevel(mitigationCount,
- mayPerformReboot(failedPackage));
+ final int level;
+ if (Flags.recoverabilityDetection()) {
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ level = getRescueLevel(mitigationCount, mayPerformReboot(failedPackage),
+ failedPackage);
+ } else {
+ level = getRescueLevel(mitigationCount);
+ }
+ } else {
+ level = getRescueLevel(mitigationCount, mayPerformReboot(failedPackage));
+ }
executeRescueLevel(mContext,
failedPackage == null ? null : failedPackage.getPackageName(), level);
return true;
@@ -787,8 +873,12 @@
return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
}
if (Flags.recoverabilityDetection()) {
- return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
- true, /*failedPackage=*/ null));
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+ true, /*failedPackage=*/ null));
+ } else {
+ return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount));
+ }
} else {
return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true));
}
@@ -800,9 +890,17 @@
return false;
}
boolean mayPerformReboot = !shouldThrottleReboot();
- final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount,
- mayPerformReboot, /*failedPackage=*/ null)
- : getRescueLevel(mitigationCount, mayPerformReboot);
+ final int level;
+ if (Flags.recoverabilityDetection()) {
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ level = getRescueLevel(mitigationCount, mayPerformReboot,
+ /*failedPackage=*/ null);
+ } else {
+ level = getRescueLevel(mitigationCount);
+ }
+ } else {
+ level = getRescueLevel(mitigationCount, mayPerformReboot);
+ }
executeRescueLevel(mContext, /*failedPackage=*/ null, level);
return true;
}
@@ -828,18 +926,6 @@
return isPersistentSystemApp(failingPackage.getPackageName());
}
- /**
- * Returns {@code true} if Rescue Party is allowed to attempt a reboot or factory reset.
- * Will return {@code false} if a factory reset was already offered recently.
- */
- private boolean shouldThrottleReboot() {
- Long lastResetTime = getLastFactoryResetTimeMs();
- long now = System.currentTimeMillis();
- long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG,
- DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN);
- return now < lastResetTime + TimeUnit.MINUTES.toMillis(throttleDurationMin);
- }
-
private boolean isPersistentSystemApp(@NonNull String packageName) {
PackageManager pm = mContext.getPackageManager();
try {
@@ -852,20 +938,22 @@
private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage,
@NonNull String namespace) {
- // Record it in calling packages to namespace map
- Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage);
- if (namespaceSet == null) {
- namespaceSet = new ArraySet<>();
- mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet);
+ if (!Flags.deprecateFlagsAndSettingsResets()) {
+ // Record it in calling packages to namespace map
+ Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage);
+ if (namespaceSet == null) {
+ namespaceSet = new ArraySet<>();
+ mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet);
+ }
+ namespaceSet.add(namespace);
+ // Record it in namespace to calling packages map
+ Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace);
+ if (callingPackageSet == null) {
+ callingPackageSet = new ArraySet<>();
+ }
+ callingPackageSet.add(callingPackage);
+ mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet);
}
- namespaceSet.add(namespace);
- // Record it in namespace to calling packages map
- Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace);
- if (callingPackageSet == null) {
- callingPackageSet = new ArraySet<>();
- }
- callingPackageSet.add(callingPackage);
- mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet);
}
private synchronized Set<String> getAffectedNamespaceSet(String failedPackage) {
@@ -881,6 +969,18 @@
}
}
+ /**
+ * Returns {@code true} if Rescue Party is allowed to attempt a reboot or factory reset.
+ * Will return {@code false} if a factory reset was already offered recently.
+ */
+ private static boolean shouldThrottleReboot() {
+ Long lastResetTime = getLastFactoryResetTimeMs();
+ long now = System.currentTimeMillis();
+ long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG,
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN);
+ return now < lastResetTime + TimeUnit.MINUTES.toMillis(throttleDurationMin);
+ }
+
private static int[] getAllUserIds() {
int systemUserId = UserHandle.SYSTEM.getIdentifier();
int[] userIds = { systemUserId };
@@ -919,6 +1019,22 @@
}
}
+ private static class Level {
+ static int none() {
+ return Flags.recoverabilityDetection() ? RESCUE_LEVEL_NONE : LEVEL_NONE;
+ }
+
+ static int reboot() {
+ return Flags.recoverabilityDetection() ? RESCUE_LEVEL_WARM_REBOOT : LEVEL_WARM_REBOOT;
+ }
+
+ static int factoryReset() {
+ return Flags.recoverabilityDetection()
+ ? RESCUE_LEVEL_FACTORY_RESET
+ : LEVEL_FACTORY_RESET;
+ }
+ }
+
private static String levelToString(int level) {
if (Flags.recoverabilityDetection()) {
switch (level) {
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
index 598f086..4faadcb 100644
--- a/services/core/java/com/android/server/am/LmkdConnection.java
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -91,10 +91,18 @@
@GuardedBy("mLmkdSocketLock")
private LocalSocket mLmkdSocket = null;
- // socket I/O streams
- @GuardedBy("mLmkdSocketLock")
+ // mutex to synchronize socket output stream with socket creation/destruction
+ private final Object mLmkdOutputStreamLock = new Object();
+
+ // socket output stream
+ @GuardedBy("mLmkdOutputStreamLock")
private OutputStream mLmkdOutputStream = null;
- @GuardedBy("mLmkdSocketLock")
+
+ // mutex to synchronize socket input stream with socket creation/destruction
+ private final Object mLmkdInputStreamLock = new Object();
+
+ // socket input stream
+ @GuardedBy("mLmkdInputStreamLock")
private InputStream mLmkdInputStream = null;
// buffer to store incoming data
@@ -148,9 +156,13 @@
return false;
}
// connection established
- mLmkdSocket = socket;
- mLmkdOutputStream = ostream;
- mLmkdInputStream = istream;
+ synchronized(mLmkdOutputStreamLock) {
+ synchronized(mLmkdInputStreamLock) {
+ mLmkdSocket = socket;
+ mLmkdOutputStream = ostream;
+ mLmkdInputStream = istream;
+ }
+ }
mMsgQueue.addOnFileDescriptorEventListener(mLmkdSocket.getFileDescriptor(),
EVENT_INPUT | EVENT_ERROR,
new MessageQueue.OnFileDescriptorEventListener() {
@@ -177,7 +189,13 @@
mMsgQueue.removeOnFileDescriptorEventListener(
mLmkdSocket.getFileDescriptor());
IoUtils.closeQuietly(mLmkdSocket);
- mLmkdSocket = null;
+ synchronized(mLmkdOutputStreamLock) {
+ synchronized(mLmkdInputStreamLock) {
+ mLmkdOutputStream = null;
+ mLmkdInputStream = null;
+ mLmkdSocket = null;
+ }
+ }
}
// wake up reply waiters if any
synchronized (mReplyBufLock) {
@@ -262,24 +280,33 @@
}
private boolean write(ByteBuffer buf) {
- synchronized (mLmkdSocketLock) {
- try {
- mLmkdOutputStream.write(buf.array(), 0, buf.position());
- } catch (IOException ex) {
- return false;
+ boolean result = false;
+
+ synchronized(mLmkdOutputStreamLock) {
+ if (mLmkdOutputStream != null) {
+ try {
+ mLmkdOutputStream.write(buf.array(), 0, buf.position());
+ result = true;
+ } catch (IOException ex) {
+ }
}
- return true;
}
+
+ return result;
}
private int read(ByteBuffer buf) {
- synchronized (mLmkdSocketLock) {
- try {
- return mLmkdInputStream.read(buf.array(), 0, buf.array().length);
- } catch (IOException ex) {
+ int result = -1;
+
+ synchronized(mLmkdInputStreamLock) {
+ if (mLmkdInputStream != null) {
+ try {
+ result = mLmkdInputStream.read(buf.array(), 0, buf.array().length);
+ } catch (IOException ex) {
+ }
}
- return -1;
}
+ return result;
}
/**
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 7157646..7aae91b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1773,6 +1773,20 @@
}
}
+ @Override
+ public boolean writeRepairModeCredential(int userId) {
+ checkWritePermission();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSpManager) {
+ long protectorId = getCurrentLskfBasedProtectorId(userId);
+ return mSpManager.writeRepairModeCredentialLocked(protectorId, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
/**
* @param savedCredential if the user is a profile with
* {@link UserManager#isCredentialSharableWithParent()} with unified challenge and
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 89c4f0f..9199004 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -4550,7 +4550,7 @@
PackageManagerException.INTERNAL_ERROR_SYSTEM_OVERLAY_STATIC);
}
} else {
- if ((scanFlags & SCAN_AS_VENDOR) != 0) {
+ if ((scanFlags & (SCAN_AS_VENDOR | SCAN_AS_ODM)) != 0) {
if (pkg.getTargetSdkVersion() < ScanPackageUtils.getVendorPartitionVersion()) {
Slog.w(TAG, "System overlay " + pkg.getPackageName()
+ " targets an SDK below the required SDK level of vendor"
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index d1f91c8..c4e3fa4 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -16,6 +16,8 @@
package com.android.server.rollback;
+import static android.crashrecovery.flags.Flags.deprecateFlagsAndSettingsResets;
+
import static com.android.server.rollback.RollbackManagerServiceImpl.sendFailure;
import android.Manifest;
@@ -622,8 +624,10 @@
parentSession.addChildSessionId(sessionId);
}
- // Clear flags.
- RescueParty.resetDeviceConfigForPackages(packageNames);
+ if (!deprecateFlagsAndSettingsResets()) {
+ // Clear flags.
+ RescueParty.resetDeviceConfigForPackages(packageNames);
+ }
Consumer<Intent> onResult = result -> {
mHandler.post(() -> {
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 3377899..f2acbc3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -27,7 +27,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.RescueParty.DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN;
import static com.android.server.RescueParty.LEVEL_FACTORY_RESET;
-import static com.android.server.RescueParty.RESCUE_LEVEL_FACTORY_RESET;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -36,7 +35,6 @@
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
import android.content.ContentResolver;
import android.content.Context;
@@ -47,6 +45,9 @@
import android.os.RecoverySystem;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -61,6 +62,9 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
@@ -77,10 +81,14 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+
/**
* Test RescueParty.
*/
+@RunWith(Parameterized.class)
public class RescuePartyTest {
+ @Rule
+ public SetFlagsRule mSetFlagsRule;
private static final long CURRENT_NETWORK_TIME_MILLIS = 0L;
private static final String FAKE_NATIVE_NAMESPACE1 = "native1";
private static final String FAKE_NATIVE_NAMESPACE2 = "native2";
@@ -103,9 +111,6 @@
private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
"persist.device_config.configuration.disable_rescue_party_factory_reset";
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
private MockitoSession mSession;
private HashMap<String, String> mSystemSettingsMap;
private HashMap<String, String> mCrashRecoveryPropertiesMap;
@@ -129,6 +134,17 @@
@Captor
private ArgumentCaptor<List<String>> mPackageListCaptor;
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getFlags() {
+ return FlagsParameterization.allCombinationsOf(
+ Flags.FLAG_RECOVERABILITY_DETECTION,
+ Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS);
+ }
+
+ public RescuePartyTest(FlagsParameterization flags) {
+ mSetFlagsRule = new SetFlagsRule(flags);
+ }
+
@Before
public void setUp() throws Exception {
mSession =
@@ -234,10 +250,10 @@
}
@Test
- public void testBootLoopDetectionWithExecutionForAllRescueLevels() {
+ @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION,
+ Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS})
+ public void testBootLoop() {
// this is old test where the flag needs to be disabled
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
-
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -264,10 +280,22 @@
noteBoot(5);
assertTrue(RescueParty.isFactoryResetPropertySet());
}
+ @Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testBootLoopNoFlags() {
+ // this is old test where the flag needs to be disabled
+ noteBoot(1);
+ assertTrue(RescueParty.isRebootPropertySet());
+
+ setCrashRecoveryPropAttemptingReboot(false);
+ noteBoot(2);
+ assertTrue(RescueParty.isFactoryResetPropertySet());
+ }
@Test
- public void testBootLoopDetectionWithExecutionForAllRescueLevelsRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION)
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testBootLoopRecoverability() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -281,12 +309,14 @@
final String[] expectedAllResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2};
+
noteBoot(1);
noteBoot(2);
assertTrue(RescueParty.isRebootPropertySet());
noteBoot(3);
+
verifyOnlySettingsReset(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
noteBoot(4);
@@ -301,10 +331,10 @@
}
@Test
- public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
+ @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION,
+ Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS})
+ public void testPersistentAppCrash() {
// this is old test where the flag needs to be disabled
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
-
noteAppCrash(1, true);
noteAppCrash(2, true);
noteAppCrash(3, true);
@@ -318,8 +348,21 @@
}
@Test
- public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevelsRecoverability() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testPersistentAppCrashNoFlags() {
+ // this is old test where the flag needs to be disabled
+ noteAppCrash(1, true);
+ assertTrue(RescueParty.isRebootPropertySet());
+
+ setCrashRecoveryPropAttemptingReboot(false);
+ noteAppCrash(2, true);
+ assertTrue(RescueParty.isFactoryResetPropertySet());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION)
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testPersistentAppCrashRecoverability() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -357,10 +400,10 @@
}
@Test
- public void testNonPersistentAppDoesntDoAnything() {
+ @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION,
+ Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS})
+ public void testNonPersistentApp() {
// this is old test where the flag needs to be disabled
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
-
noteAppCrash(1, false);
noteAppCrash(2, false);
noteAppCrash(3, false);
@@ -371,8 +414,9 @@
}
@Test
+ @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION)
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
public void testNonPersistentAppOnlyPerformsFlagResetsRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -408,60 +452,6 @@
}
@Test
- public void testNonPersistentAppCrashDetectionWithScopedResets() {
- // this is old test where the flag needs to be disabled
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
-
- RescueParty.onSettingsProviderPublished(mMockContext);
- verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
- any(Executor.class),
- mMonitorCallbackCaptor.capture()));
-
- // Record DeviceConfig accesses
- RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
- DeviceConfig.MonitorCallback monitorCallback = mMonitorCallbackCaptor.getValue();
- monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE1, NAMESPACE1);
- monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE1, NAMESPACE2);
- monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE2, NAMESPACE2);
- monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE2, NAMESPACE3);
-
- // Fake DeviceConfig value changes
- monitorCallback.onNamespaceUpdate(NAMESPACE1);
- verify(mMockPackageWatchdog).startObservingHealth(observer,
- Arrays.asList(CALLING_PACKAGE1), RescueParty.DEFAULT_OBSERVING_DURATION_MS);
- monitorCallback.onNamespaceUpdate(NAMESPACE2);
- verify(mMockPackageWatchdog, times(2)).startObservingHealth(eq(observer),
- mPackageListCaptor.capture(),
- eq(RescueParty.DEFAULT_OBSERVING_DURATION_MS));
- monitorCallback.onNamespaceUpdate(NAMESPACE3);
- verify(mMockPackageWatchdog).startObservingHealth(observer,
- Arrays.asList(CALLING_PACKAGE2), RescueParty.DEFAULT_OBSERVING_DURATION_MS);
- assertTrue(mPackageListCaptor.getValue().containsAll(
- Arrays.asList(CALLING_PACKAGE1, CALLING_PACKAGE2)));
- // Perform and verify scoped resets
- final String[] expectedResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2};
- final String[] expectedAllResetNamespaces =
- new String[]{NAMESPACE1, NAMESPACE2, NAMESPACE3};
- HashMap<String, Integer> verifiedTimesMap = new HashMap<String, Integer>();
- observer.execute(new VersionedPackage(
- CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
-
- observer.execute(new VersionedPackage(
- CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 2);
-
- observer.execute(new VersionedPackage(
- CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 3);
-
- observer.execute(new VersionedPackage(
- CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
- assertFalse(RescueParty.isRebootPropertySet());
-
- observer.execute(new VersionedPackage(
- CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
- assertFalse(RescueParty.isFactoryResetPropertySet());
- }
-
- @Test
public void testIsRecoveryTriggeredReboot() {
for (int i = 0; i < LEVEL_FACTORY_RESET; i++) {
noteBoot(i + 1);
@@ -474,19 +464,6 @@
}
@Test
- public void testIsRecoveryTriggeredRebootRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- for (int i = 0; i < RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteBoot(i + 1);
- }
- assertFalse(RescueParty.isFactoryResetPropertySet());
- setCrashRecoveryPropAttemptingReboot(false);
- noteBoot(RESCUE_LEVEL_FACTORY_RESET + 1);
- assertTrue(RescueParty.isRecoveryTriggeredReboot());
- assertTrue(RescueParty.isFactoryResetPropertySet());
- }
-
- @Test
public void testIsRecoveryTriggeredRebootOnlyAfterRebootCompleted() {
for (int i = 0; i < LEVEL_FACTORY_RESET; i++) {
noteBoot(i + 1);
@@ -505,25 +482,6 @@
}
@Test
- public void testIsRecoveryTriggeredRebootOnlyAfterRebootCompletedRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- for (int i = 0; i < RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteBoot(i + 1);
- }
- int mitigationCount = RESCUE_LEVEL_FACTORY_RESET + 1;
- assertFalse(RescueParty.isFactoryResetPropertySet());
- noteBoot(mitigationCount++);
- assertFalse(RescueParty.isFactoryResetPropertySet());
- noteBoot(mitigationCount++);
- assertFalse(RescueParty.isFactoryResetPropertySet());
- noteBoot(mitigationCount++);
- setCrashRecoveryPropAttemptingReboot(false);
- noteBoot(mitigationCount + 1);
- assertTrue(RescueParty.isRecoveryTriggeredReboot());
- assertTrue(RescueParty.isFactoryResetPropertySet());
- }
-
- @Test
public void testThrottlingOnBootFailures() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
@@ -537,20 +495,6 @@
}
@Test
- public void testThrottlingOnBootFailuresRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- setCrashRecoveryPropAttemptingReboot(false);
- long now = System.currentTimeMillis();
- long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
- DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
- setCrashRecoveryPropLastFactoryReset(beforeTimeout);
- for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteBoot(i);
- }
- assertFalse(RescueParty.isRecoveryTriggeredReboot());
- }
-
- @Test
public void testThrottlingOnAppCrash() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
@@ -564,20 +508,6 @@
}
@Test
- public void testThrottlingOnAppCrashRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- setCrashRecoveryPropAttemptingReboot(false);
- long now = System.currentTimeMillis();
- long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
- DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
- setCrashRecoveryPropLastFactoryReset(beforeTimeout);
- for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteAppCrash(i + 1, true);
- }
- assertFalse(RescueParty.isRecoveryTriggeredReboot());
- }
-
- @Test
public void testNotThrottlingAfterTimeoutOnBootFailures() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
@@ -591,20 +521,6 @@
}
@Test
- public void testNotThrottlingAfterTimeoutOnBootFailuresRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- setCrashRecoveryPropAttemptingReboot(false);
- long now = System.currentTimeMillis();
- long afterTimeout = now - TimeUnit.MINUTES.toMillis(
- DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
- setCrashRecoveryPropLastFactoryReset(afterTimeout);
- for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteBoot(i);
- }
- assertTrue(RescueParty.isRecoveryTriggeredReboot());
- }
-
- @Test
public void testNotThrottlingAfterTimeoutOnAppCrash() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
@@ -618,20 +534,7 @@
}
@Test
- public void testNotThrottlingAfterTimeoutOnAppCrashRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- setCrashRecoveryPropAttemptingReboot(false);
- long now = System.currentTimeMillis();
- long afterTimeout = now - TimeUnit.MINUTES.toMillis(
- DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
- setCrashRecoveryPropLastFactoryReset(afterTimeout);
- for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteAppCrash(i + 1, true);
- }
- assertTrue(RescueParty.isRecoveryTriggeredReboot());
- }
-
- @Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
public void testNativeRescuePartyResets() {
doReturn(true).when(() -> SettingsToPropertiesMapper.isNativeFlagsResetPerformed());
doReturn(FAKE_RESET_NATIVE_NAMESPACES).when(
@@ -647,7 +550,6 @@
@Test
public void testExplicitlyEnablingAndDisablingRescue() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(false));
SystemProperties.set(PROP_DISABLE_RESCUE, Boolean.toString(true));
assertEquals(RescuePartyObserver.getInstance(mMockContext).execute(sFailingPackage,
@@ -660,7 +562,6 @@
@Test
public void testDisablingRescueByDeviceConfigFlag() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(false));
SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(true));
@@ -686,24 +587,10 @@
}
@Test
- public void testDisablingFactoryResetByDeviceConfigFlagRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, Boolean.toString(true));
-
- for (int i = 0; i < RESCUE_LEVEL_FACTORY_RESET; i++) {
- noteBoot(i + 1);
- }
- assertFalse(RescueParty.isFactoryResetPropertySet());
-
- // Restore the property value initialized in SetUp()
- SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, "");
- }
-
- @Test
+ @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION,
+ Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS})
public void testHealthCheckLevels() {
// this is old test where the flag needs to be disabled
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
-
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
// Ensure that no action is taken for cases where the failure reason is unknown
@@ -729,8 +616,9 @@
}
@Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION)
public void testHealthCheckLevelsRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
// Ensure that no action is taken for cases where the failure reason is unknown
@@ -767,11 +655,31 @@
PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 7),
PackageHealthObserverImpact.USER_IMPACT_LEVEL_40);
}
-
@Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testHealthCheckLevelsNoFlags() {
+ // this is old test where the flag needs to be disabled
+ RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
+
+ // Ensure that no action is taken for cases where the failure reason is unknown
+ assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_UNKNOWN, 1),
+ PackageHealthObserverImpact.USER_IMPACT_LEVEL_0);
+
+ // Ensure the correct user impact is returned for each mitigation count.
+ assertEquals(observer.onHealthCheckFailed(null,
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 1),
+ PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
+
+ assertEquals(observer.onHealthCheckFailed(null,
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 2),
+ PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
+ }
+ @Test
+ @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION,
+ Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS})
public void testBootLoopLevels() {
// this is old test where the flag needs to be disabled
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
@@ -784,8 +692,9 @@
}
@Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION)
public void testBootLoopLevelsRecoverabilityDetection() {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LEVEL_40);
@@ -797,6 +706,16 @@
}
@Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testBootLoopLevelsNoFlags() {
+ RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
+
+ assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
+ assertEquals(observer.onBootLoop(2), PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
public void testResetDeviceConfigForPackagesOnlyRuntimeMap() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
@@ -827,6 +746,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
public void testResetDeviceConfigForPackagesOnlyPresetMap() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
@@ -835,7 +755,7 @@
String presetMapping = NAMESPACE1 + ":" + CALLING_PACKAGE1 + ","
+ NAMESPACE2 + ":" + CALLING_PACKAGE2 + ","
- + NAMESPACE3 + ":" + CALLING_PACKAGE1;
+ + NAMESPACE3 + ":" + CALLING_PACKAGE1;
doReturn(presetMapping).when(() -> DeviceConfig.getString(
eq(RescueParty.NAMESPACE_CONFIGURATION),
eq(RescueParty.NAMESPACE_TO_PACKAGE_MAPPING_FLAG),
@@ -848,6 +768,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
public void testResetDeviceConfigForPackagesBothMaps() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
@@ -884,6 +805,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
public void testResetDeviceConfigNoExceptionWhenFlagMalformed() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java
index 70150c5..4396c67 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java
@@ -19,6 +19,8 @@
import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE;
import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
@@ -199,6 +201,27 @@
.getResponseCode());
}
+ @Test
+ public void writeRepairModeCredential_noLock() {
+ assertThat(mService.writeRepairModeCredential(PRIMARY_USER_ID)).isFalse();
+ }
+
+ @Test
+ public void writeRepairModeCredential_hasLock() {
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+ assertThat(mService.writeRepairModeCredential(PRIMARY_USER_ID)).isTrue();
+ }
+
+ @Test
+ public void writeRepairModeCredential_verifyRepairModeUser() {
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+ mService.writeRepairModeCredential(PRIMARY_USER_ID);
+ setRepairModeActive(true);
+
+ var response = mService.verifyCredential(newPin("1234"), USER_REPAIR_MODE, 0);
+ assertThat(response.isMatched()).isTrue();
+ }
+
private void setRepairModeActive(boolean active) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.REPAIR_MODE_ACTIVE, active ? 1 : 0);