summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/SurfaceControl.java2
-rw-r--r--packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java82
-rw-r--r--packages/CrashRecovery/services/java/com/android/server/RescueParty.java6
-rw-r--r--packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java115
-rw-r--r--packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java103
-rw-r--r--packages/CrashRecovery/services/java/com/android/utils/FileUtils.java128
-rw-r--r--packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java46
-rw-r--r--packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java188
-rw-r--r--packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java118
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java2
-rw-r--r--services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java42
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java557
-rw-r--r--tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java116
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java69
-rw-r--r--tests/UsbManagerTests/Android.bp1
-rw-r--r--tests/UsbTests/Android.bp1
17 files changed, 697 insertions, 888 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cbbe7856178d..6dd0a9077a67 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1247,7 +1247,7 @@ public final class SurfaceControl implements Parcelable {
* surface has no buffer or crop, the surface is boundless and only constrained
* by the size of its parent bounds.
*
- * @param session The surface session, must not be null.
+ * @param session The surface session.
* @param name The surface name, must not be null.
* @param w The surface initial width.
* @param h The surface initial height.
diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
index a8d8f9a1a55d..6f20adf74ee2 100644
--- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
+++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
@@ -39,15 +39,15 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.LongArrayQueue;
import android.util.Slog;
import android.util.Xml;
-import android.utils.BackgroundThread;
-import android.utils.LongArrayQueue;
-import android.utils.XmlUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -137,17 +137,6 @@ public class PackageWatchdog {
static final int DEFAULT_BOOT_LOOP_TRIGGER_COUNT = 5;
static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10);
- // Boot loop at which packageWatchdog starts first mitigation
- private static final String BOOT_LOOP_THRESHOLD =
- "persist.device_config.configuration.boot_loop_threshold";
- @VisibleForTesting
- static final int DEFAULT_BOOT_LOOP_THRESHOLD = 15;
- // Once boot_loop_threshold is surpassed next mitigation would be triggered after
- // specified number of reboots.
- private static final String BOOT_LOOP_MITIGATION_INCREMENT =
- "persist.device_config.configuration..boot_loop_mitigation_increment";
- @VisibleForTesting
- static final int DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT = 2;
// Threshold level at which or above user might experience significant disruption.
private static final String MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
@@ -253,15 +242,8 @@ public class PackageWatchdog {
mConnectivityModuleConnector = connectivityModuleConnector;
mSystemClock = clock;
mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
- if (Flags.recoverabilityDetection()) {
- mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
- DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
- SystemProperties.getInt(BOOT_LOOP_MITIGATION_INCREMENT,
- DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
- } else {
- mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
- DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS);
- }
+ mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
+ DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS);
loadFromFile();
sPackageWatchdog = this;
@@ -526,10 +508,16 @@ public class PackageWatchdog {
/**
* Called when the system server boots. If the system server is detected to be in a boot loop,
* query each observer and perform the mitigation action with the lowest user impact.
+ *
+ * Note: PackageWatchdog considers system_server restart loop as bootloop. Full reboots
+ * are not counted in bootloop.
*/
@SuppressWarnings("GuardedBy")
public void noteBoot() {
synchronized (mLock) {
+ // if boot count has reached threshold, start mitigation.
+ // We wait until threshold number of restarts only for the first time. Perform
+ // mitigations for every restart after that.
boolean mitigate = mBootThreshold.incrementAndTest();
if (mitigate) {
if (!Flags.recoverabilityDetection()) {
@@ -557,17 +545,13 @@ public class PackageWatchdog {
}
if (currentObserverToNotify != null) {
if (Flags.recoverabilityDetection()) {
- if (currentObserverImpact < getUserImpactLevelLimit()
- || (currentObserverImpact >= getUserImpactLevelLimit()
- && mBootThreshold.getCount() >= getBootLoopThreshold())) {
- int currentObserverMitigationCount =
- currentObserverInternal.getBootMitigationCount() + 1;
- currentObserverInternal.setBootMitigationCount(
- currentObserverMitigationCount);
- saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
- currentObserverToNotify.executeBootLoopMitigation(
- currentObserverMitigationCount);
- }
+ int currentObserverMitigationCount =
+ currentObserverInternal.getBootMitigationCount() + 1;
+ currentObserverInternal.setBootMitigationCount(
+ currentObserverMitigationCount);
+ saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
+ currentObserverToNotify.executeBootLoopMitigation(
+ currentObserverMitigationCount);
} else {
mBootThreshold.setMitigationCount(mitigationCount);
mBootThreshold.saveMitigationCountToMetadata();
@@ -647,11 +631,6 @@ public class PackageWatchdog {
DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD);
}
- private int getBootLoopThreshold() {
- return SystemProperties.getInt(BOOT_LOOP_THRESHOLD,
- DEFAULT_BOOT_LOOP_THRESHOLD);
- }
-
/** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */
@Retention(SOURCE)
@IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
@@ -1827,16 +1806,10 @@ public class PackageWatchdog {
private final int mBootTriggerCount;
private final long mTriggerWindow;
- private final int mBootMitigationIncrement;
BootThreshold(int bootTriggerCount, long triggerWindow) {
- this(bootTriggerCount, triggerWindow, /*bootMitigationIncrement=*/ 1);
- }
-
- BootThreshold(int bootTriggerCount, long triggerWindow, int bootMitigationIncrement) {
this.mBootTriggerCount = bootTriggerCount;
this.mTriggerWindow = triggerWindow;
- this.mBootMitigationIncrement = bootMitigationIncrement;
}
public void reset() {
@@ -1915,6 +1888,7 @@ public class PackageWatchdog {
} else {
readMitigationCountFromMetadataIfNecessary();
}
+
final long now = mSystemClock.uptimeMillis();
if (now - getStart() < 0) {
Slog.e(TAG, "Window was less than zero. Resetting start to current time.");
@@ -1939,20 +1913,32 @@ public class PackageWatchdog {
setCount(count);
EventLogTags.writeRescueNote(Process.ROOT_UID, count, window);
if (Flags.recoverabilityDetection()) {
- boolean mitigate = (count >= mBootTriggerCount)
- && (count - mBootTriggerCount) % mBootMitigationIncrement == 0;
- return mitigate;
+ // After a reboot (e.g. by WARM_REBOOT or mainline rollback) we apply
+ // mitigations without waiting for DEFAULT_BOOT_LOOP_TRIGGER_COUNT.
+ return (count >= mBootTriggerCount)
+ || (performedMitigationsDuringWindow() && count > 1);
}
return count >= mBootTriggerCount;
}
}
@GuardedBy("mLock")
+ private boolean performedMitigationsDuringWindow() {
+ for (ObserverInternal observerInternal: mAllObservers.values()) {
+ if (observerInternal.getBootMitigationCount() > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @GuardedBy("mLock")
private void resetAllObserversBootMitigationCount() {
for (int i = 0; i < mAllObservers.size(); i++) {
final ObserverInternal observer = mAllObservers.valueAt(i);
observer.setBootMitigationCount(0);
}
+ saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
}
@GuardedBy("mLock")
diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
index 7093ba42f40d..271d552fc574 100644
--- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
+++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
@@ -31,6 +31,7 @@ import android.content.pm.VersionedPackage;
import android.crashrecovery.flags.Flags;
import android.os.Build;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.PowerManager;
import android.os.RecoverySystem;
import android.os.SystemClock;
@@ -43,11 +44,10 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
-import android.utils.ArrayUtils;
-import android.utils.FileUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
@@ -139,7 +139,7 @@ public class RescueParty {
static final String NAMESPACE_TO_PACKAGE_MAPPING_FLAG =
"namespace_to_package_mapping";
@VisibleForTesting
- static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 10;
+ static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 1440;
private static final String NAME = "rescue-party-observer";
diff --git a/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java b/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java
deleted file mode 100644
index fa4d6afc03d3..000000000000
--- a/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.File;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Copied over from frameworks/base/core/java/com/android/internal/util/ArrayUtils.java
- *
- * @hide
- */
-public class ArrayUtils {
- private ArrayUtils() { /* cannot be instantiated */ }
- public static final File[] EMPTY_FILE = new File[0];
-
-
- /**
- * Return first index of {@code value} in {@code array}, or {@code -1} if
- * not found.
- */
- public static <T> int indexOf(@Nullable T[] array, T value) {
- if (array == null) return -1;
- for (int i = 0; i < array.length; i++) {
- if (Objects.equals(array[i], value)) return i;
- }
- return -1;
- }
-
- /** @hide */
- public static @NonNull File[] defeatNullable(@Nullable File[] val) {
- return (val != null) ? val : EMPTY_FILE;
- }
-
- /**
- * Checks if given array is null or has zero elements.
- */
- public static boolean isEmpty(@Nullable int[] array) {
- return array == null || array.length == 0;
- }
-
- /**
- * True if the byte array is null or has length 0.
- */
- public static boolean isEmpty(@Nullable byte[] array) {
- return array == null || array.length == 0;
- }
-
- /**
- * Converts from List of bytes to byte array
- * @param list
- * @return byte[]
- */
- public static byte[] toPrimitive(List<byte[]> list) {
- if (list.size() == 0) {
- return new byte[0];
- }
- int byteLen = list.get(0).length;
- byte[] array = new byte[list.size() * byteLen];
- for (int i = 0; i < list.size(); i++) {
- for (int j = 0; j < list.get(i).length; j++) {
- array[i * byteLen + j] = list.get(i)[j];
- }
- }
- return array;
- }
-
- /**
- * Adds value to given array if not already present, providing set-like
- * behavior.
- */
- public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
- return appendInt(cur, val, false);
- }
-
- /**
- * Adds value to given array.
- */
- public static @NonNull int[] appendInt(@Nullable int[] cur, int val,
- boolean allowDuplicates) {
- if (cur == null) {
- return new int[] { val };
- }
- final int n = cur.length;
- if (!allowDuplicates) {
- for (int i = 0; i < n; i++) {
- if (cur[i] == val) {
- return cur;
- }
- }
- }
- int[] ret = new int[n + 1];
- System.arraycopy(cur, 0, ret, 0, n);
- ret[n] = val;
- return ret;
- }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java b/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java
deleted file mode 100644
index afcf6895fd0d..000000000000
--- a/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * * 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.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.os.Handler;
-import android.os.HandlerThread;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.concurrent.Executor;
-
-/**
- * Thread for asynchronous event processing. This thread is configured as
- * {@link android.os.Process#THREAD_PRIORITY_BACKGROUND}, which means fewer CPU
- * resources will be dedicated to it, and it will "have less chance of impacting
- * the responsiveness of the user interface."
- * <p>
- * This thread is best suited for tasks that the user is not actively waiting
- * for, or for tasks that the user expects to be executed eventually.
- *
- * @see com.android.internal.os.BackgroundThread
- *
- * TODO: b/326916057 depend on modules-utils-backgroundthread instead
- * @hide
- */
-public final class BackgroundThread extends HandlerThread {
- private static final Object sLock = new Object();
-
- @GuardedBy("sLock")
- private static BackgroundThread sInstance;
- @GuardedBy("sLock")
- private static Handler sHandler;
- @GuardedBy("sLock")
- private static HandlerExecutor sHandlerExecutor;
-
- private BackgroundThread() {
- super(BackgroundThread.class.getName(), android.os.Process.THREAD_PRIORITY_BACKGROUND);
- }
-
- @GuardedBy("sLock")
- private static void ensureThreadLocked() {
- if (sInstance == null) {
- sInstance = new BackgroundThread();
- sInstance.start();
- sHandler = new Handler(sInstance.getLooper());
- sHandlerExecutor = new HandlerExecutor(sHandler);
- }
- }
-
- /**
- * Get the singleton instance of this class.
- *
- * @return the singleton instance of this class
- */
- @NonNull
- public static BackgroundThread get() {
- synchronized (sLock) {
- ensureThreadLocked();
- return sInstance;
- }
- }
-
- /**
- * Get the singleton {@link Handler} for this class.
- *
- * @return the singleton {@link Handler} for this class.
- */
- @NonNull
- public static Handler getHandler() {
- synchronized (sLock) {
- ensureThreadLocked();
- return sHandler;
- }
- }
-
- /**
- * Get the singleton {@link Executor} for this class.
- *
- * @return the singleton {@link Executor} for this class.
- */
- @NonNull
- public static Executor getExecutor() {
- synchronized (sLock) {
- ensureThreadLocked();
- return sHandlerExecutor;
- }
- }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java b/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java
deleted file mode 100644
index e4923bfc4ecb..000000000000
--- a/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Bits and pieces copied from hidden API of android.os.FileUtils.
- *
- * @hide
- */
-public class FileUtils {
- /**
- * Read a text file into a String, optionally limiting the length.
- *
- * @param file to read (will not seek, so things like /proc files are OK)
- * @param max length (positive for head, negative of tail, 0 for no limit)
- * @param ellipsis to add of the file was truncated (can be null)
- * @return the contents of the file, possibly truncated
- * @throws IOException if something goes wrong reading the file
- * @hide
- */
- public static @Nullable String readTextFile(@Nullable File file, @Nullable int max,
- @Nullable String ellipsis) throws IOException {
- InputStream input = new FileInputStream(file);
- // wrapping a BufferedInputStream around it because when reading /proc with unbuffered
- // input stream, bytes read not equal to buffer size is not necessarily the correct
- // indication for EOF; but it is true for BufferedInputStream due to its implementation.
- BufferedInputStream bis = new BufferedInputStream(input);
- try {
- long size = file.length();
- if (max > 0 || (size > 0 && max == 0)) { // "head" mode: read the first N bytes
- if (size > 0 && (max == 0 || size < max)) max = (int) size;
- byte[] data = new byte[max + 1];
- int length = bis.read(data);
- if (length <= 0) return "";
- if (length <= max) return new String(data, 0, length);
- if (ellipsis == null) return new String(data, 0, max);
- return new String(data, 0, max) + ellipsis;
- } else if (max < 0) { // "tail" mode: keep the last N
- int len;
- boolean rolled = false;
- byte[] last = null;
- byte[] data = null;
- do {
- if (last != null) rolled = true;
- byte[] tmp = last;
- last = data;
- data = tmp;
- if (data == null) data = new byte[-max];
- len = bis.read(data);
- } while (len == data.length);
-
- if (last == null && len <= 0) return "";
- if (last == null) return new String(data, 0, len);
- if (len > 0) {
- rolled = true;
- System.arraycopy(last, len, last, 0, last.length - len);
- System.arraycopy(data, 0, last, last.length - len, len);
- }
- if (ellipsis == null || !rolled) return new String(last);
- return ellipsis + new String(last);
- } else { // "cat" mode: size unknown, read it all in streaming fashion
- ByteArrayOutputStream contents = new ByteArrayOutputStream();
- int len;
- byte[] data = new byte[1024];
- do {
- len = bis.read(data);
- if (len > 0) contents.write(data, 0, len);
- } while (len == data.length);
- return contents.toString();
- }
- } finally {
- bis.close();
- input.close();
- }
- }
-
- /**
- * Perform an fsync on the given FileOutputStream. The stream at this
- * point must be flushed but not yet closed.
- *
- * @hide
- */
- public static boolean sync(FileOutputStream stream) {
- try {
- if (stream != null) {
- stream.getFD().sync();
- }
- return true;
- } catch (IOException e) {
- }
- return false;
- }
-
- /**
- * List the files in the directory or return empty file.
- *
- * @hide
- */
- public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {
- return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles())
- : ArrayUtils.EMPTY_FILE;
- }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java b/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java
deleted file mode 100644
index fdb15e2333d5..000000000000
--- a/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.os.Handler;
-
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
-
-/**
- * An adapter {@link Executor} that posts all executed tasks onto the given
- * {@link Handler}.
- *
- * TODO: b/326916057 depend on modules-utils-backgroundthread instead
- * @hide
- */
-public class HandlerExecutor implements Executor {
- private final Handler mHandler;
-
- public HandlerExecutor(@NonNull Handler handler) {
- mHandler = Objects.requireNonNull(handler);
- }
-
- @Override
- public void execute(Runnable command) {
- if (!mHandler.post(command)) {
- throw new RejectedExecutionException(mHandler + " is shutting down");
- }
- }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java b/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java
deleted file mode 100644
index 5cdc2536129a..000000000000
--- a/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.
- */
-
-package android.utils;
-
-import libcore.util.EmptyArray;
-
-import java.util.NoSuchElementException;
-
-/**
- * Copied from frameworks/base/core/java/android/util/LongArrayQueue.java
- *
- * @hide
- */
-public class LongArrayQueue {
-
- private long[] mValues;
- private int mSize;
- private int mHead;
- private int mTail;
-
- private long[] newUnpaddedLongArray(int num) {
- return new long[num];
- }
- /**
- * Initializes a queue with the given starting capacity.
- *
- * @param initialCapacity the capacity.
- */
- public LongArrayQueue(int initialCapacity) {
- if (initialCapacity == 0) {
- mValues = EmptyArray.LONG;
- } else {
- mValues = newUnpaddedLongArray(initialCapacity);
- }
- mSize = 0;
- mHead = mTail = 0;
- }
-
- /**
- * Initializes a queue with default starting capacity.
- */
- public LongArrayQueue() {
- this(16);
- }
-
- /** @hide */
- public static int growSize(int currentSize) {
- return currentSize <= 4 ? 8 : currentSize * 2;
- }
-
- private void grow() {
- if (mSize < mValues.length) {
- throw new IllegalStateException("Queue not full yet!");
- }
- final int newSize = growSize(mSize);
- final long[] newArray = newUnpaddedLongArray(newSize);
- final int r = mValues.length - mHead; // Number of elements on and to the right of head.
- System.arraycopy(mValues, mHead, newArray, 0, r);
- System.arraycopy(mValues, 0, newArray, r, mHead);
- mValues = newArray;
- mHead = 0;
- mTail = mSize;
- }
-
- /**
- * Returns the number of elements in the queue.
- */
- public int size() {
- return mSize;
- }
-
- /**
- * Removes all elements from this queue.
- */
- public void clear() {
- mSize = 0;
- mHead = mTail = 0;
- }
-
- /**
- * Adds a value to the tail of the queue.
- *
- * @param value the value to be added.
- */
- public void addLast(long value) {
- if (mSize == mValues.length) {
- grow();
- }
- mValues[mTail] = value;
- mTail = (mTail + 1) % mValues.length;
- mSize++;
- }
-
- /**
- * Removes an element from the head of the queue.
- *
- * @return the element at the head of the queue.
- * @throws NoSuchElementException if the queue is empty.
- */
- public long removeFirst() {
- if (mSize == 0) {
- throw new NoSuchElementException("Queue is empty!");
- }
- final long ret = mValues[mHead];
- mHead = (mHead + 1) % mValues.length;
- mSize--;
- return ret;
- }
-
- /**
- * Returns the element at the given position from the head of the queue, where 0 represents the
- * head of the queue.
- *
- * @param position the position from the head of the queue.
- * @return the element found at the given position.
- * @throws IndexOutOfBoundsException if {@code position} < {@code 0} or
- * {@code position} >= {@link #size()}
- */
- public long get(int position) {
- if (position < 0 || position >= mSize) {
- throw new IndexOutOfBoundsException("Index " + position
- + " not valid for a queue of size " + mSize);
- }
- final int index = (mHead + position) % mValues.length;
- return mValues[index];
- }
-
- /**
- * Returns the element at the head of the queue, without removing it.
- *
- * @return the element at the head of the queue.
- * @throws NoSuchElementException if the queue is empty
- */
- public long peekFirst() {
- if (mSize == 0) {
- throw new NoSuchElementException("Queue is empty!");
- }
- return mValues[mHead];
- }
-
- /**
- * Returns the element at the tail of the queue.
- *
- * @return the element at the tail of the queue.
- * @throws NoSuchElementException if the queue is empty.
- */
- public long peekLast() {
- if (mSize == 0) {
- throw new NoSuchElementException("Queue is empty!");
- }
- final int index = (mTail == 0) ? mValues.length - 1 : mTail - 1;
- return mValues[index];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- if (mSize <= 0) {
- return "{}";
- }
-
- final StringBuilder buffer = new StringBuilder(mSize * 64);
- buffer.append('{');
- buffer.append(get(0));
- for (int i = 1; i < mSize; i++) {
- buffer.append(", ");
- buffer.append(get(i));
- }
- buffer.append('}');
- return buffer.toString();
- }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java b/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java
deleted file mode 100644
index dbbef61f6777..000000000000
--- a/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.system.ErrnoException;
-import android.system.Os;
-
-import com.android.modules.utils.TypedXmlPullParser;
-
-import libcore.util.XmlObjectFactory;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Copied over partly from frameworks/base/core/java/com/android/internal/util/XmlUtils.java
- *
- * @hide
- */
-public class XmlUtils {
-
- private static final String STRING_ARRAY_SEPARATOR = ":";
-
- /** @hide */
- public static final void beginDocument(XmlPullParser parser, String firstElementName)
- throws XmlPullParserException, IOException {
- int type;
- while ((type = parser.next()) != parser.START_TAG
- && type != parser.END_DOCUMENT) {
- // Do nothing
- }
-
- if (type != parser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- if (!parser.getName().equals(firstElementName)) {
- throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
- + ", expected " + firstElementName);
- }
- }
-
- /** @hide */
- public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
- throws IOException, XmlPullParserException {
- for (;;) {
- int type = parser.next();
- if (type == XmlPullParser.END_DOCUMENT
- || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
- return false;
- }
- if (type == XmlPullParser.START_TAG
- && parser.getDepth() == outerDepth + 1) {
- return true;
- }
- }
- }
-
- private static XmlPullParser newPullParser() {
- try {
- XmlPullParser parser = XmlObjectFactory.newXmlPullParser();
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true);
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- return parser;
- } catch (XmlPullParserException e) {
- throw new AssertionError();
- }
- }
-
- /** @hide */
- public static @NonNull TypedXmlPullParser resolvePullParser(@NonNull InputStream in)
- throws IOException {
- final byte[] magic = new byte[4];
- if (in instanceof FileInputStream) {
- try {
- Os.pread(((FileInputStream) in).getFD(), magic, 0, magic.length, 0);
- } catch (ErrnoException e) {
- throw e.rethrowAsIOException();
- }
- } else {
- if (!in.markSupported()) {
- in = new BufferedInputStream(in);
- }
- in.mark(8);
- in.read(magic);
- in.reset();
- }
-
- final TypedXmlPullParser xml;
- xml = (TypedXmlPullParser) newPullParser();
- try {
- xml.setInput(in, "UTF_8");
- } catch (XmlPullParserException e) {
- throw new IOException(e);
- }
- return xml;
- }
-}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index e876527fc513..4dfa71b7ad36 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -350,6 +350,7 @@ public final class ProcessList {
// LMK_UPDATE_PROPS
// LMK_KILL_OCCURRED
// LMK_START_MONITORING
+ // LMK_BOOT_COMPLETED
static final byte LMK_TARGET = 0;
static final byte LMK_PROCPRIO = 1;
static final byte LMK_PROCREMOVE = 2;
@@ -360,6 +361,7 @@ public final class ProcessList {
static final byte LMK_UPDATE_PROPS = 7;
static final byte LMK_KILL_OCCURRED = 8; // Msg to subscribed clients on kill occurred event
static final byte LMK_START_MONITORING = 9; // Start monitoring if delayed earlier
+ static final byte LMK_BOOT_COMPLETED = 10;
// Low Memory Killer Daemon command codes.
// These must be kept in sync with async_event_type definitions in lmkd.h
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 0f40ca082663..2783fefa5b71 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -198,8 +198,7 @@ final class UpdatableFontDir {
File signatureFile = new File(dir, FONT_SIGNATURE_FILE);
if (!signatureFile.exists()) {
Slog.i(TAG, "The signature file is missing.");
- FileUtils.deleteContentsAndDir(dir);
- continue;
+ return;
}
byte[] signature;
try {
@@ -224,10 +223,36 @@ final class UpdatableFontDir {
FontFileInfo fontFileInfo = validateFontFile(fontFile, signature);
if (fontConfig == null) {
- fontConfig = getSystemFontConfig();
+ // Use preinstalled font config for checking revision number.
+ fontConfig = mConfigSupplier.apply(Collections.emptyMap());
}
addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, true /* deleteOldFile */);
}
+
+ // Treat as error if post script name of font family was not installed.
+ for (int i = 0; i < config.fontFamilies.size(); ++i) {
+ FontUpdateRequest.Family family = config.fontFamilies.get(i);
+ for (int j = 0; j < family.getFonts().size(); ++j) {
+ FontUpdateRequest.Font font = family.getFonts().get(j);
+ if (mFontFileInfoMap.containsKey(font.getPostScriptName())) {
+ continue;
+ }
+
+ if (fontConfig == null) {
+ fontConfig = mConfigSupplier.apply(Collections.emptyMap());
+ }
+
+ if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) {
+ continue;
+ }
+
+ Slog.e(TAG, "Unknown font that has PostScript name "
+ + font.getPostScriptName() + " is requested in FontFamily "
+ + family.getName());
+ return;
+ }
+ }
+
success = true;
} catch (Throwable t) {
// If something happened during loading system fonts, clear all contents in finally
@@ -239,6 +264,7 @@ final class UpdatableFontDir {
mFontFileInfoMap.clear();
mLastModifiedMillis = 0;
FileUtils.deleteContents(mFilesDir);
+ mConfigFile.delete();
}
}
}
@@ -487,8 +513,7 @@ final class UpdatableFontDir {
return shouldAddToMap;
}
- private long getPreinstalledFontRevision(FontFileInfo info, FontConfig fontConfig) {
- String psName = info.getPostScriptName();
+ private FontConfig.Font getFontByPostScriptName(String psName, FontConfig fontConfig) {
FontConfig.Font targetFont = null;
for (int i = 0; i < fontConfig.getFontFamilies().size(); i++) {
FontConfig.FontFamily family = fontConfig.getFontFamilies().get(i);
@@ -513,6 +538,13 @@ final class UpdatableFontDir {
}
}
}
+ return targetFont;
+ }
+
+ private long getPreinstalledFontRevision(FontFileInfo info, FontConfig fontConfig) {
+ String psName = info.getPostScriptName();
+ FontConfig.Font targetFont = getFontByPostScriptName(psName, fontConfig);
+
if (targetFont == null) {
return -1;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 682569f1d9ab..697548cbe2b4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -1111,16 +1111,9 @@ public class RescuePartyTest {
// mock properties in BootThreshold
try {
- if (Flags.recoverabilityDetection()) {
- mSpyBootThreshold = spy(watchdog.new BootThreshold(
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
- PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
- } else {
- mSpyBootThreshold = spy(watchdog.new BootThreshold(
+ mSpyBootThreshold = spy(watchdog.new BootThreshold(
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
- }
mCrashRecoveryPropertiesMap = new HashMap<>();
doAnswer((Answer<Integer>) invocationOnMock -> {
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index 3de167e72ba0..5fb15e9c4df0 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -1001,6 +1001,563 @@ public final class UpdatableFontDirTest {
assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
}
+ private UpdatableFontDir createNewUpdateDir() {
+ UpdatableFontDir dir = new UpdatableFontDir(
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
+ mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+ dir.loadFontFileMap();
+ return dir;
+ }
+
+ private UpdatableFontDir installTestFontFamilies(int version) {
+ UpdatableFontDir dir = createNewUpdateDir();
+ try {
+ dir.update(Arrays.asList(
+ newFontUpdateRequest("foo.ttf," + version + ",foo", GOOD_SIGNATURE),
+ newFontUpdateRequest("bar.ttf," + version + ",bar", GOOD_SIGNATURE),
+ newAddFontFamilyRequest("<family name='foobar'>"
+ + " <font>foo.ttf</font>"
+ + " <font>bar.ttf</font>"
+ + "</family>")));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return dir;
+ }
+
+ private UpdatableFontDir installTestFontFile(int numFonts, int version) {
+ UpdatableFontDir dir = createNewUpdateDir();
+ List<FontUpdateRequest> requests = new ArrayList<>();
+ if (numFonts <= 0 || numFonts > 3) {
+ throw new IllegalArgumentException("numFont must be 1, 2 or 3");
+ }
+ try {
+ requests.add(newFontUpdateRequest("foo.ttf," + version + ",foo", GOOD_SIGNATURE));
+ if (numFonts >= 2) {
+ requests.add(newFontUpdateRequest("bar.ttf," + version + ",bar", GOOD_SIGNATURE));
+ }
+ if (numFonts == 3) {
+ requests.add(newFontUpdateRequest("baz.ttf," + version + ",baz", GOOD_SIGNATURE));
+ }
+ dir.update(requests);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return dir;
+ }
+
+ private List<File> collectSignatureFiles() {
+ return Arrays.stream(mUpdatableFontFilesDir.listFiles())
+ .map((file) -> file.listFiles((unused, s) -> s.endsWith(".fsv_sig")))
+ .flatMap(Arrays::stream)
+ .toList();
+ }
+
+ private List<File> collectFontFiles() {
+ return Arrays.stream(mUpdatableFontFilesDir.listFiles())
+ .map((file) -> file.listFiles((unused, s) -> s.endsWith(".ttf")))
+ .flatMap(Arrays::stream)
+ .toList();
+ }
+
+ private void removeAll(List<File> files) {
+ files.forEach((File file) -> {
+ if (file.isDirectory()) {
+ removeAll(List.of(file.listFiles()));
+ } else {
+ assertThat(file.delete()).isTrue();
+ }
+ });
+ }
+
+ private void assertTestFontFamilyInstalled(UpdatableFontDir dir, int version) {
+ try {
+ assertNamedFamilyExists(dir.getSystemFontConfig(), "foobar");
+ assertThat(dir.getFontFamilyMap()).containsKey("foobar");
+ assertThat(dir.getFontFamilyMap().get("foobar").getFamilies().size()).isEqualTo(1);
+ FontConfig.FontFamily foobar = dir.getFontFamilyMap().get("foobar").getFamilies()
+ .get(0);
+ assertThat(foobar.getFontList()).hasSize(2);
+ assertThat(foobar.getFontList().get(0).getFile())
+ .isEqualTo(dir.getPostScriptMap().get("foo"));
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(version);
+ assertThat(foobar.getFontList().get(1).getFile())
+ .isEqualTo(dir.getPostScriptMap().get("bar"));
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(version);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void assertTestFontInstalled(UpdatableFontDir dir, int version) {
+ try {
+ assertThat(dir.getPostScriptMap().containsKey("foo")).isTrue();
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(version);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void signatureMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(2 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(2 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
private FontUpdateRequest newFontUpdateRequest(String content, String signature)
throws Exception {
File file = File.createTempFile("font", "ttf", mCacheDir);
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 081da11f2aa8..489ef4444e1d 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -66,6 +66,7 @@ import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
@@ -220,43 +221,36 @@ public class CrashRecoveryTest {
RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(1);
- int bootCounter = 0;
+
for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
watchdog.noteBoot();
- bootCounter += 1;
}
+
verify(rescuePartyObserver).executeBootLoopMitigation(1);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- bootCounter += 1;
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(2);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
- int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
- for (int i = 0; i < bootLoopThreshold; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(3);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(4);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(4);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(5);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(5);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(6);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(7);
}
@@ -268,11 +262,11 @@ public class CrashRecoveryTest {
setUpRollbackPackageHealthObserver(watchdog);
verify(rollbackObserver, never()).executeBootLoopMitigation(1);
- int bootCounter = 0;
+
for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
watchdog.noteBoot();
- bootCounter += 1;
}
+
verify(rollbackObserver).executeBootLoopMitigation(1);
verify(rollbackObserver, never()).executeBootLoopMitigation(2);
@@ -280,19 +274,16 @@ public class CrashRecoveryTest {
when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_HIGH,
ROLLBACK_INFO_MANUAL));
- int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
- for (int i = 0; i < bootLoopThreshold; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rollbackObserver).executeBootLoopMitigation(2);
verify(rollbackObserver, never()).executeBootLoopMitigation(3);
// Update the list of available rollbacks after executing bootloop mitigation once
when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_MANUAL));
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rollbackObserver, never()).executeBootLoopMitigation(3);
}
@@ -305,27 +296,21 @@ public class CrashRecoveryTest {
verify(rescuePartyObserver, never()).executeBootLoopMitigation(1);
verify(rollbackObserver, never()).executeBootLoopMitigation(1);
- int bootCounter = 0;
for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
watchdog.noteBoot();
- bootCounter += 1;
}
verify(rescuePartyObserver).executeBootLoopMitigation(1);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
verify(rollbackObserver, never()).executeBootLoopMitigation(1);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- bootCounter += 1;
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(2);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
verify(rollbackObserver, never()).executeBootLoopMitigation(2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- bootCounter += 1;
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
verify(rollbackObserver).executeBootLoopMitigation(1);
verify(rollbackObserver, never()).executeBootLoopMitigation(2);
@@ -333,43 +318,46 @@ public class CrashRecoveryTest {
when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_HIGH,
ROLLBACK_INFO_MANUAL));
- int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
- for (int i = 0; i < bootLoopThreshold; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(3);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(4);
verify(rollbackObserver, never()).executeBootLoopMitigation(2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(4);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(5);
verify(rollbackObserver, never()).executeBootLoopMitigation(2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(5);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
verify(rollbackObserver, never()).executeBootLoopMitigation(2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
verify(rollbackObserver).executeBootLoopMitigation(2);
verify(rollbackObserver, never()).executeBootLoopMitigation(3);
// Update the list of available rollbacks after executing bootloop mitigation
when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_MANUAL));
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
- watchdog.noteBoot();
- }
+ watchdog.noteBoot();
+
verify(rescuePartyObserver).executeBootLoopMitigation(6);
verify(rescuePartyObserver, never()).executeBootLoopMitigation(7);
verify(rollbackObserver, never()).executeBootLoopMitigation(3);
+
+ moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
+ Mockito.reset(rescuePartyObserver);
+
+ for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
+ watchdog.noteBoot();
+ }
+ verify(rescuePartyObserver).executeBootLoopMitigation(1);
+ verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
}
RollbackPackageHealthObserver setUpRollbackPackageHealthObserver(PackageWatchdog watchdog) {
@@ -506,16 +494,9 @@ public class CrashRecoveryTest {
}
try {
- if (Flags.recoverabilityDetection()) {
- mSpyBootThreshold = spy(watchdog.new BootThreshold(
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
- PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
- } else {
- mSpyBootThreshold = spy(watchdog.new BootThreshold(
+ mSpyBootThreshold = spy(watchdog.new BootThreshold(
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
- }
doAnswer((Answer<Integer>) invocationOnMock -> {
String storedValue = mCrashRecoveryPropertiesMap
@@ -640,5 +621,16 @@ public class CrashRecoveryTest {
public long uptimeMillis() {
return mUpTimeMillis;
}
+ public void moveTimeForward(long milliSeconds) {
+ mUpTimeMillis += milliSeconds;
+ }
+ }
+
+ private void moveTimeForwardAndDispatch(long milliSeconds) {
+ // Exhaust all due runnables now which shouldn't be executed after time-leap
+ mTestLooper.dispatchAll();
+ mTestClock.moveTimeForward(milliSeconds);
+ mTestLooper.moveTimeForward(milliSeconds);
+ mTestLooper.dispatchAll();
}
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 4f27e06083ba..093923f3ed53 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -45,13 +45,13 @@ import android.os.test.TestLooper;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;
import android.util.AtomicFile;
+import android.util.LongArrayQueue;
import android.util.Xml;
-import android.utils.LongArrayQueue;
-import android.utils.XmlUtils;
import androidx.test.InstrumentationRegistry;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.PackageWatchdog.HealthCheckState;
@@ -1224,7 +1224,7 @@ public class PackageWatchdogTest {
PackageWatchdog watchdog = createWatchdog();
TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
watchdog.registerHealthObserver(bootObserver);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD; i++) {
+ for (int i = 0; i < 15; i++) {
watchdog.noteBoot();
}
assertThat(bootObserver.mitigatedBootLoop()).isTrue();
@@ -1262,22 +1262,6 @@ public class PackageWatchdogTest {
}
/**
- * Ensure that boot loop mitigation is not done when the number of boots does not meet the
- * threshold.
- */
- @Test
- public void testBootLoopDetection_doesNotMeetThresholdRecoverabilityHighImpact() {
- PackageWatchdog watchdog = createWatchdog();
- TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_80);
- watchdog.registerHealthObserver(bootObserver);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; i++) {
- watchdog.noteBoot();
- }
- assertThat(bootObserver.mitigatedBootLoop()).isFalse();
- }
-
- /**
* Ensure that boot loop mitigation is done for the observer with the lowest user impact
*/
@Test
@@ -1306,7 +1290,7 @@ public class PackageWatchdogTest {
bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
watchdog.registerHealthObserver(bootObserver1);
watchdog.registerHealthObserver(bootObserver2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD; i++) {
+ for (int i = 0; i < 15; i++) {
watchdog.noteBoot();
}
assertThat(bootObserver1.mitigatedBootLoop()).isTrue();
@@ -1349,9 +1333,7 @@ public class PackageWatchdogTest {
watchdog.noteBoot();
}
for (int i = 0; i < 4; i++) {
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
watchdog.noteBoot();
- }
}
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
@@ -1360,38 +1342,7 @@ public class PackageWatchdogTest {
watchdog.noteBoot();
}
for (int i = 0; i < 4; i++) {
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
watchdog.noteBoot();
- }
- }
-
- assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
- }
-
- @Test
- public void testMultipleBootLoopMitigationRecoverabilityHighImpact() {
- PackageWatchdog watchdog = createWatchdog();
- TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_80);
- watchdog.registerHealthObserver(bootObserver);
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; j++) {
- watchdog.noteBoot();
- }
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
- watchdog.noteBoot();
- }
- }
-
- moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
-
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; j++) {
- watchdog.noteBoot();
- }
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
- watchdog.noteBoot();
- }
}
assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
@@ -1642,8 +1593,7 @@ public class PackageWatchdogTest {
mSpyBootThreshold = spy(watchdog.new BootThreshold(
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
- PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
+ PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
watchdog.saveAllObserversBootMitigationCountToMetadata(filePath);
@@ -1798,16 +1748,9 @@ public class PackageWatchdogTest {
mCrashRecoveryPropertiesMap = new HashMap<>();
try {
- if (Flags.recoverabilityDetection()) {
- mSpyBootThreshold = spy(watchdog.new BootThreshold(
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
- PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
- PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
- } else {
- mSpyBootThreshold = spy(watchdog.new BootThreshold(
+ mSpyBootThreshold = spy(watchdog.new BootThreshold(
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
- }
doAnswer((Answer<Integer>) invocationOnMock -> {
String storedValue = mCrashRecoveryPropertiesMap
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
index c02d8e96abb0..a0bb84d09664 100644
--- a/tests/UsbManagerTests/Android.bp
+++ b/tests/UsbManagerTests/Android.bp
@@ -21,6 +21,7 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_android_usb",
}
android_test {
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index 92c271165ad7..c4ebdecae735 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -21,6 +21,7 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_android_usb",
}
android_test {