summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/AndroidManifest.xml12
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java75
-rw-r--r--apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java21
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java4
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/app/NotificationChannel.java6
-rw-r--r--core/java/android/view/WindowManager.java27
-rw-r--r--core/java/android/view/WindowManagerGlobal.java2
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl1
-rw-r--r--graphics/java/android/graphics/Typeface.java29
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt26
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt27
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt60
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt45
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt57
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt60
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt60
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeUi.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java2
-rw-r--r--services/core/java/com/android/server/am/UserController.java31
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java6
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/AppDataHelper.java2
-rw-r--r--services/core/java/com/android/server/pm/DeletePackageHelper.java27
-rw-r--r--services/core/java/com/android/server/pm/FileInstallArgs.java268
-rw-r--r--services/core/java/com/android/server/pm/InstallArgs.java40
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java390
-rw-r--r--services/core/java/com/android/server/pm/InstallingSession.java318
-rw-r--r--services/core/java/com/android/server/pm/MoveInstallArgs.java133
-rw-r--r--services/core/java/com/android/server/pm/MultiPackageInstallingSession.java107
-rw-r--r--services/core/java/com/android/server/pm/PackageHandler.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java4
-rw-r--r--services/core/java/com/android/server/pm/ReconciledPackage.java3
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java112
-rw-r--r--services/core/java/com/android/server/pm/ScanPackageUtils.java3
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java11
-rw-r--r--services/core/java/com/android/server/pm/Settings.java25
-rw-r--r--services/core/java/com/android/server/pm/SharedLibrariesImpl.java137
-rw-r--r--services/core/java/com/android/server/pm/StorageEventHelper.java4
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt18
-rw-r--r--services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java46
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt49
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt21
47 files changed, 1067 insertions, 1307 deletions
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml
index eb3fb891965e..c153201cd475 100644
--- a/apct-tests/perftests/core/AndroidManifest.xml
+++ b/apct-tests/perftests/core/AndroidManifest.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.android.perftests.core">
<permission android:name="com.android.perftests.core.TestPermission" />
@@ -33,6 +34,17 @@
android:exported="false"
android:process=":some_provider" />
+ <!-- We remove EmojiCompat initializer here because it may crash the test process
+ if the initializer runs while TypefaceSerializationPerfTest is running. -->
+ <provider
+ android:name="androidx.startup.InitializationProvider"
+ android:authorities="${applicationId}.androidx-startup"
+ android:exported="false"
+ tools:node="merge">
+ <meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer"
+ tools:node="remove" />
+ </provider>
+
<service
android:name="android.view.autofill.MyAutofillService"
android:label="PERF AutofillService"
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java
index d27250719c6d..675ff0107081 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java
@@ -17,10 +17,13 @@
package android.graphics.perftests;
import android.graphics.Typeface;
+import android.os.Debug;
import android.os.SharedMemory;
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
+import android.os.SystemClock;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.PerfManualStatusReporter;
import android.util.ArrayMap;
+import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -37,16 +40,33 @@ import java.util.Map;
@RunWith(AndroidJUnit4.class)
public class TypefaceSerializationPerfTest {
+ private static final String TAG = "TypefaceSerializationPerfTest";
+
@Rule
- public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
@Test
public void testSerializeFontMap() throws Exception {
Map<String, Typeface> systemFontMap = Typeface.getSystemFontMap();
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
+ long elapsedTime = 0;
+ while (state.keepRunning(elapsedTime)) {
+ long startTime = System.nanoTime();
Typeface.serializeFontMap(systemFontMap);
+ elapsedTime = System.nanoTime() - startTime;
+ }
+ }
+
+ @Test
+ public void testSerializeFontMap_memory() throws Exception {
+ Map<String, Typeface> systemFontMap = Typeface.getSystemFontMap();
+ SharedMemory memory = Typeface.serializeFontMap(systemFontMap);
+ ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
+
+ while (state.keepRunning(memory.getSize())) {
+ // Rate-limiting
+ SystemClock.sleep(100);
}
}
@@ -54,22 +74,54 @@ public class TypefaceSerializationPerfTest {
public void testDeserializeFontMap() throws Exception {
SharedMemory memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
ByteBuffer buffer = memory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
+
+ ArrayMap<String, Typeface> out = new ArrayMap<>();
+ long elapsedTime = 0;
+ while (state.keepRunning(elapsedTime)) {
+ long startTime = System.nanoTime();
+ buffer.position(0);
+ Typeface.deserializeFontMap(buffer, out);
+ elapsedTime = System.nanoTime() - startTime;
+ }
+ }
+
+ @Test
+ public void testDeserializeFontMap_memory() throws Exception {
+ SharedMemory memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
+ ByteBuffer buffer = memory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
+ ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
ArrayMap<String, Typeface> out = new ArrayMap<>();
- while (state.keepRunning()) {
+ // Diff of native heap allocation size (in bytes) before and after deserializeFontMap.
+ // Note: we don't measure memory usage of setSystemFontMap because setSystemFontMap sets
+ // some global variables, and it's hard to clear them.
+ long heapDiff = 0;
+ // Sometimes heapDiff may become negative due to GC.
+ // Use 0 in that case to avoid crashing in keepRunning.
+ while (state.keepRunning(Math.max(0, heapDiff))) {
buffer.position(0);
+ long baselineSize = Debug.getNativeHeapAllocatedSize();
Typeface.deserializeFontMap(buffer, out);
+ long currentSize = Debug.getNativeHeapAllocatedSize();
+ heapDiff = currentSize - baselineSize;
+ Log.i(TAG, String.format("native heap alloc: current = %d, baseline = %d, diff = %d",
+ currentSize, baselineSize, heapDiff));
+ // Release native objects here to minimize the impact of GC.
+ for (Typeface typeface : out.values()) {
+ typeface.releaseNativeObjectForTest();
+ }
+ out.clear();
}
}
@Test
public void testSetSystemFontMap() throws Exception {
SharedMemory memory = null;
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
- state.pauseTiming();
+ long elapsedTime = 0;
+ while (state.keepRunning(elapsedTime)) {
// Explicitly destroy lazy-loaded typefaces, so that we don't hit the mmap limit
// (max_map_count).
Typeface.destroySystemFontMap();
@@ -78,8 +130,9 @@ public class TypefaceSerializationPerfTest {
memory.close();
}
memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
- state.resumeTiming();
+ long startTime = System.nanoTime();
Typeface.setSystemFontMap(memory);
+ elapsedTime = System.nanoTime() - startTime;
}
}
}
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 734545376279..448ee6160ce0 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -15,6 +15,7 @@
*/
package android.multiuser;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
@@ -42,6 +43,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.perftests.utils.ShellHelper;
+import android.text.TextUtils;
import android.util.Log;
import android.view.WindowManagerGlobal;
@@ -116,13 +118,14 @@ public class UserLifecycleTests {
private boolean mHasManagedUserFeature;
private BroadcastWaiter mBroadcastWaiter;
private UserSwitchWaiter mUserSwitchWaiter;
+ private String mUserSwitchTimeoutMs;
private final BenchmarkRunner mRunner = new BenchmarkRunner();
@Rule
public BenchmarkResultsReporter mReporter = new BenchmarkResultsReporter(mRunner);
@Before
- public void setUp() {
+ public void setUp() throws Exception {
final Context context = InstrumentationRegistry.getContext();
mUm = UserManager.get(context);
mAm = context.getSystemService(ActivityManager.class);
@@ -141,10 +144,16 @@ public class UserLifecycleTests {
Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser()
+ " rather than the system user");
}
+ mUserSwitchTimeoutMs = setSystemProperty("debug.usercontroller.user_switch_timeout_ms",
+ "100000");
+ if (TextUtils.isEmpty(mUserSwitchTimeoutMs)) {
+ mUserSwitchTimeoutMs = "invalid";
+ }
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
+ setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs);
mBroadcastWaiter.close();
for (int userId : mUsersToRemove) {
try {
@@ -236,7 +245,7 @@ public class UserLifecycleTests {
/** Tests switching to an uninitialized user. */
@Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
- public void switchUser() throws RemoteException {
+ public void switchUser() throws Exception {
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int startUser = mAm.getCurrentUser();
@@ -867,4 +876,10 @@ public class UserLifecycleTests {
private void attestFalse(@NonNull String message, boolean assertion) {
attestTrue(message, !assertion);
}
+
+ private String setSystemProperty(String name, String value) throws Exception {
+ final String oldValue = ShellHelper.runShellCommand("getprop " + name);
+ assertEquals("", ShellHelper.runShellCommand("setprop " + name + " " + value));
+ return oldValue;
+ }
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 68801bcac4ba..dd80acb80de2 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -303,7 +303,9 @@ public final class JobServiceContext implements ServiceConnection {
getStartActionId(job), String.valueOf(job.getJobId()));
mVerb = VERB_BINDING;
scheduleOpTimeOutLocked();
- final Intent intent = new Intent().setComponent(job.getServiceComponent());
+ // Use FLAG_FROM_BACKGROUND to avoid resetting the bad-app tracking.
+ final Intent intent = new Intent().setComponent(job.getServiceComponent())
+ .setFlags(Intent.FLAG_FROM_BACKGROUND);
boolean binding = false;
try {
final int bindFlags;
diff --git a/core/api/current.txt b/core/api/current.txt
index 93bbd8267d25..805435a757d1 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -51539,6 +51539,7 @@ package android.view {
method public default boolean isCrossWindowBlurEnabled();
method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void removeViewImmediate(android.view.View);
+ field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
}
public static class WindowManager.BadTokenException extends java.lang.RuntimeException {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index c9cc1a179102..0e89b25eb37d 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -564,8 +564,10 @@ public final class NotificationChannel implements Parcelable {
/**
* Sets the vibration pattern for notifications posted to this channel. If the provided
- * pattern is valid (non-null, non-empty), will {@link #enableVibration(boolean)} enable
- * vibration} as well. Otherwise, vibration will be disabled.
+ * pattern is valid (non-null, non-empty), will enable vibration on this channel
+ * (equivalent to calling {@link #enableVibration(boolean)} with {@code true}).
+ * Otherwise, vibration will be disabled unless {@link #enableVibration(boolean)} is
+ * used with {@code true}, in which case the default vibration will be used.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 13ea7af7a623..b8808eebee8e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -820,6 +820,33 @@ public interface WindowManager extends ViewManager {
public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
/**
+ * Application level {@link android.content.pm.PackageManager.Property} tag for developers to
+ * provide consent for their app to allow OEMs to manually provide ActivityEmbedding split
+ * rule configuration on behalf of the app.
+ *
+ * <p>If {@code true}, the system CAN override the windowing behaviors for the app, such as
+ * showing some activities side-by-side. In this case, it will report that ActivityEmbedding
+ * APIs are disabled for the app to avoid conflict.
+ *
+ * <p>If {@code false}, the system MUST NOT override the window behavior for the app. It should
+ * be used if the app wants to provide their own ActivityEmbedding split rules, or if the app
+ * wants to opt-out of system overrides for any other reason.
+ *
+ * <p>Default is {@code false}.
+ *
+ * <p>Example usage:
+ * <pre>
+ * &lt;application&gt;
+ * &lt;property
+ * android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
+ * android:value="true|false"/&gt;
+ * &lt;/application&gt;
+ * </pre>
+ */
+ String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE =
+ "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
+
+ /**
* Request for keyboard shortcuts to be retrieved asynchronously.
*
* @param receiver The callback to be triggered when the result is ready.
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index ac4c2ea448ac..d37756551db3 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -404,7 +404,7 @@ public final class WindowManagerGlobal {
try {
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
- final int viewIndex = findViewLocked(view, false);
+ final int viewIndex = (index >= 0) ? index : (mViews.size() - 1);
// BadTokenException or InvalidDisplayException, clean up.
if (viewIndex >= 0) {
removeViewLocked(viewIndex, true);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 25c00c222665..95cb729b3f7f 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -124,6 +124,7 @@ interface IInputMethodManager {
boolean isStylusHandwritingAvailableAsUser(int userId);
/** add virtual stylus id for test Stylus handwriting session **/
+ @EnforcePermission("INJECT_EVENTS")
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.INJECT_EVENTS)")
void addVirtualStylusIdForTestSession(in IInputMethodClient client);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index a2f5301e353f..8e3acb8570f0 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1176,6 +1176,17 @@ public class Typeface {
mWeight = nativeGetWeight(ni);
}
+ /**
+ * Releases the underlying native object.
+ *
+ * <p>For testing only. Do not use the instance after this method is called.
+ * It is safe to call this method twice or more on the same instance.
+ * @hide
+ */
+ public void releaseNativeObjectForTest() {
+ mCleaner.run();
+ }
+
private static Typeface getSystemDefaultTypeface(@NonNull String familyName) {
Typeface tf = sSystemFontMap.get(familyName);
return tf == null ? Typeface.DEFAULT : tf;
@@ -1425,7 +1436,7 @@ public class Typeface {
public static void destroySystemFontMap() {
synchronized (SYSTEM_FONT_MAP_LOCK) {
for (Typeface typeface : sSystemFontMap.values()) {
- typeface.mCleaner.run();
+ typeface.releaseNativeObjectForTest();
}
sSystemFontMap.clear();
if (sSystemFontMapBuffer != null) {
@@ -1433,7 +1444,23 @@ public class Typeface {
}
sSystemFontMapBuffer = null;
sSystemFontMapSharedMemory = null;
+ synchronized (sStyledCacheLock) {
+ destroyTypefaceCacheLocked(sStyledTypefaceCache);
+ }
+ synchronized (sWeightCacheLock) {
+ destroyTypefaceCacheLocked(sWeightTypefaceCache);
+ }
+ }
+ }
+
+ private static void destroyTypefaceCacheLocked(LongSparseArray<SparseArray<Typeface>> cache) {
+ for (int i = 0; i < cache.size(); i++) {
+ SparseArray<Typeface> array = cache.valueAt(i);
+ for (int j = 0; j < array.size(); j++) {
+ array.valueAt(j).releaseNativeObjectForTest();
+ }
}
+ cache.clear();
}
/** @hide */
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index 70771d842197..1c587a2078cf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -17,6 +17,7 @@
package com.android.wm.shell.flicker
import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -34,6 +35,7 @@ import com.android.server.wm.flicker.taskBarWindowIsAlwaysVisible
import com.android.server.wm.traces.common.ComponentMatcher
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume
+import org.junit.Test
/**
* Base test class containing common assertions for [ComponentMatcher.NAV_BAR],
@@ -80,6 +82,8 @@ abstract class BaseTest @JvmOverloads constructor(
/**
* Checks that the [ComponentMatcher.NAV_BAR] layer is visible during the whole transition
*/
+ @Presubmit
+ @Test
open fun navBarLayerIsVisibleAtStartAndEnd() {
Assume.assumeFalse(testSpec.isTablet)
testSpec.navBarLayerIsVisibleAtStartAndEnd()
@@ -88,6 +92,8 @@ abstract class BaseTest @JvmOverloads constructor(
/**
* Checks the position of the [ComponentMatcher.NAV_BAR] at the start and end of the transition
*/
+ @Presubmit
+ @Test
open fun navBarLayerPositionAtStartAndEnd() {
Assume.assumeFalse(testSpec.isTablet)
testSpec.navBarLayerPositionAtStartAndEnd()
@@ -98,6 +104,8 @@ abstract class BaseTest @JvmOverloads constructor(
*
* Note: Phones only
*/
+ @Presubmit
+ @Test
open fun navBarWindowIsAlwaysVisible() {
Assume.assumeFalse(testSpec.isTablet)
testSpec.navBarWindowIsAlwaysVisible()
@@ -106,6 +114,8 @@ abstract class BaseTest @JvmOverloads constructor(
/**
* Checks that the [ComponentMatcher.TASK_BAR] layer is visible during the whole transition
*/
+ @Presubmit
+ @Test
open fun taskBarLayerIsVisibleAtStartAndEnd() {
Assume.assumeTrue(testSpec.isTablet)
testSpec.taskBarLayerIsVisibleAtStartAndEnd()
@@ -116,6 +126,8 @@ abstract class BaseTest @JvmOverloads constructor(
*
* Note: Large screen only
*/
+ @Presubmit
+ @Test
open fun taskBarWindowIsAlwaysVisible() {
Assume.assumeTrue(testSpec.isTablet)
testSpec.taskBarWindowIsAlwaysVisible()
@@ -124,25 +136,31 @@ abstract class BaseTest @JvmOverloads constructor(
/**
* Checks that the [ComponentMatcher.STATUS_BAR] layer is visible during the whole transition
*/
+ @Presubmit
+ @Test
open fun statusBarLayerIsVisibleAtStartAndEnd() =
testSpec.statusBarLayerIsVisibleAtStartAndEnd()
/**
* Checks the position of the [ComponentMatcher.STATUS_BAR] at the start and end of the transition
*/
+ @Presubmit
+ @Test
open fun statusBarLayerPositionAtStartAndEnd() = testSpec.statusBarLayerPositionAtStartAndEnd()
/**
* Checks that the [ComponentMatcher.STATUS_BAR] window is visible during the whole transition
*/
- open fun statusBarWindowIsAlwaysVisible() {
- testSpec.statusBarWindowIsAlwaysVisible()
- }
+ @Presubmit
+ @Test
+ open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
/**
* Checks that all layers that are visible on the trace, are visible for at least 2
* consecutive entries.
*/
+ @Presubmit
+ @Test
open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry()
@@ -153,6 +171,8 @@ abstract class BaseTest @JvmOverloads constructor(
* Checks that all windows that are visible on the trace, are visible for at least 2
* consecutive entries.
*/
+ @Presubmit
+ @Test
open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 07731f85193a..7b9c1bccda75 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -16,13 +16,18 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import org.junit.Assume
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -72,6 +77,8 @@ class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest
}
}
+ @Postsubmit
+ @Test
override fun pipAppLayerAlwaysVisible() {
if (!testSpec.isGesturalNavigation) super.pipAppLayerAlwaysVisible() else {
// pip layer in gesture nav will disappear during transition
@@ -83,18 +90,38 @@ class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest
}
}
+ @Postsubmit
+ @Test
override fun pipLayerReduces() {
// in gestural nav the pip enters through alpha animation
Assume.assumeFalse(testSpec.isGesturalNavigation)
super.pipLayerReduces()
}
+ @Postsubmit
+ @Test
override fun focusChanges() {
// in gestural nav the focus goes to different activity on swipe up
Assume.assumeFalse(testSpec.isGesturalNavigation)
super.focusChanges()
}
+ @Presubmit
+ @Test
+ override fun entireScreenCovered() {
+ Assume.assumeFalse(isShellTransitionsEnabled)
+ super.entireScreenCovered()
+ }
+
+ @FlakyTest(bugId = 227313015)
+ @Test
+ fun entireScreenCovered_ShellTransit() {
+ Assume.assumeTrue(isShellTransitionsEnabled)
+ super.entireScreenCovered()
+ }
+
+ @Postsubmit
+ @Test
override fun pipLayerRemainInsideVisibleBounds() {
if (!testSpec.isGesturalNavigation) super.pipLayerRemainInsideVisibleBounds() else {
// pip layer in gesture nav will disappear during transition
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 25b1dd901b6b..90ae36c88348 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -173,65 +172,6 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
}
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index f486f257e679..dff447b97b9b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -227,57 +227,14 @@ class EnterPipToOtherOrientationTest(
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 197726599)
+ @FlakyTest(bugId = 227313015)
@Test
override fun entireScreenCovered() = super.entireScreenCovered()
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 6a86a14070bb..45851c8b6326 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.wm.shell.flicker.helpers.FixedAppHelper
@@ -129,61 +128,7 @@ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTrans
}
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index 774dbfe2a9dd..a04ca09e6dd8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.FlakyTest
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -78,6 +79,11 @@ class ExitPipViaExpandButtonClickTest(
}
}
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 227313015)
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index 685f4584c92c..1d266140f2e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -109,6 +109,11 @@ class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransit
super.pipLayerExpands()
}
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 227313015)
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 430d5ae35162..1c0bd0caa901 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -167,65 +166,6 @@ class ExpandPipOnDoubleClickTest(testSpec: FlickerTestParameter) : PipTransition
}
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
index 895158b4812c..9fb941e2a584 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.traces.region.RegionSubject
@@ -110,63 +109,4 @@ abstract class MovePipShelfHeightTransition(
}
}
}
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 3d9950aa3240..911d402cfde7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -110,59 +109,6 @@ open class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testS
}
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
companion object {
private const val TAG_IME_VISIBLE = "imeIsVisible"
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 70e4fa3aa27f..7c816cec08f2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -26,8 +26,6 @@ import android.os.SystemClock;
import android.text.format.Formatter;
import android.util.Log;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -44,8 +42,6 @@ import javax.inject.Inject;
*/
@DozeScope
public class DozeUi implements DozeMachine.Part {
- // if enabled, calls dozeTimeTick() whenever the time changes:
- private static final boolean BURN_IN_TESTING_ENABLED = false;
private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
private final Context mContext;
private final DozeHost mHost;
@@ -57,26 +53,13 @@ public class DozeUi implements DozeMachine.Part {
private final DozeParameters mDozeParameters;
private final DozeLog mDozeLog;
private final StatusBarStateController mStatusBarStateController;
- private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onTimeChanged() {
- if (BURN_IN_TESTING_ENABLED && mStatusBarStateController.isDozing()) {
- // update whenever the time changes for manual burn in testing
- mHost.dozeTimeTick();
-
- // Keep wakelock until a frame has been pushed.
- mHandler.post(mWakeLock.wrap(() -> {}));
- }
- }
- };
private long mLastTimeTickElapsed = 0;
@Inject
public DozeUi(Context context, AlarmManager alarmManager,
WakeLock wakeLock, DozeHost host, @Main Handler handler,
- DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DozeParameters params,
StatusBarStateController statusBarStateController,
DozeLog dozeLog) {
mContext = context;
@@ -86,7 +69,6 @@ public class DozeUi implements DozeMachine.Part {
mCanAnimateTransition = !params.getDisplayNeedsBlanking();
mDozeParameters = params;
mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
- keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
mDozeLog = dozeLog;
mStatusBarStateController = statusBarStateController;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
index e5a75e231f8d..49cdfa72f344 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
@@ -86,7 +86,7 @@ public class DozeUiTest extends SysuiTestCase {
mHandler = mHandlerThread.getThreadHandler();
mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
- mDozeParameters, mKeyguardUpdateMonitor, mStatusBarStateController, mDozeLog);
+ mDozeParameters, mStatusBarStateController, mDozeLog);
mDozeUi.setDozeMachine(mMachine);
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 7ffea26638f5..e4224edac790 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -91,6 +91,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.EventLog;
@@ -145,7 +146,7 @@ class UserController implements Handler.Callback {
// Amount of time we wait for observers to handle a user switch before
// giving up on them and unfreezing the screen.
- static final int USER_SWITCH_TIMEOUT_MS = 3 * 1000;
+ static final int DEFAULT_USER_SWITCH_TIMEOUT_MS = 3 * 1000;
/**
* Amount of time we wait for an observer to handle a user switch before we log a warning. This
@@ -182,9 +183,11 @@ class UserController implements Handler.Callback {
// UI thread message constants
static final int START_USER_SWITCH_UI_MSG = 1000;
- // If a callback wasn't called within USER_SWITCH_CALLBACKS_TIMEOUT_MS after
- // USER_SWITCH_TIMEOUT_MS, an error is reported. Usually it indicates a problem in the observer
- // when it never calls back.
+ /**
+ * If a callback wasn't called within USER_SWITCH_CALLBACKS_TIMEOUT_MS after
+ * {@link #getUserSwitchTimeoutMs}, an error is reported. Usually it indicates a problem in the
+ * observer when it never calls back.
+ */
private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000;
/**
@@ -348,7 +351,7 @@ class UserController implements Handler.Callback {
private String mSwitchingToSystemUserMessage;
/**
- * Callbacks that are still active after {@link #USER_SWITCH_TIMEOUT_MS}
+ * Callbacks that are still active after {@link #getUserSwitchTimeoutMs}
*/
@GuardedBy("mLock")
private ArraySet<String> mTimeoutUserSwitchCallbacks;
@@ -1642,7 +1645,7 @@ class UserController implements Handler.Callback {
mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
oldUserId, userId, uss));
mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
- oldUserId, userId, uss), USER_SWITCH_TIMEOUT_MS);
+ oldUserId, userId, uss), getUserSwitchTimeoutMs());
}
if (userInfo.preCreated) {
@@ -1955,6 +1958,7 @@ class UserController implements Handler.Callback {
mCurWaitingUserSwitchCallbacks = curWaitingUserSwitchCallbacks;
}
final AtomicInteger waitingCallbacksCount = new AtomicInteger(observerCount);
+ final long userSwitchTimeoutMs = getUserSwitchTimeoutMs();
final long dispatchStartedTime = SystemClock.elapsedRealtime();
for (int i = 0; i < observerCount; i++) {
final long dispatchStartedTimeForObserver = SystemClock.elapsedRealtime();
@@ -1978,7 +1982,7 @@ class UserController implements Handler.Callback {
long totalDelay = SystemClock.elapsedRealtime()
- dispatchStartedTime;
- if (totalDelay > USER_SWITCH_TIMEOUT_MS) {
+ if (totalDelay > userSwitchTimeoutMs) {
Slogf.e(TAG, "User switch timeout: observer " + name
+ "'s result was received " + totalDelay
+ " ms after dispatchUserSwitch.");
@@ -3109,6 +3113,19 @@ class UserController implements Handler.Callback {
return bOptions;
}
+ private static int getUserSwitchTimeoutMs() {
+ final String userSwitchTimeoutMs = SystemProperties.get(
+ "debug.usercontroller.user_switch_timeout_ms");
+ if (!TextUtils.isEmpty(userSwitchTimeoutMs)) {
+ try {
+ return Integer.parseInt(userSwitchTimeoutMs);
+ } catch (NumberFormatException ignored) {
+ // Ignored.
+ }
+ }
+ return DEFAULT_USER_SWITCH_TIMEOUT_MS;
+ }
+
/**
* Uptime when any user was being unlocked most recently. 0 if no users have been unlocked
* yet. To avoid lock contention (since it's used by OomAdjuster), it's volatile internally.
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 05341e0f876e..dedc56ac9b41 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -523,10 +523,12 @@ final class LogicalDisplay {
// Set the layer stack.
device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
// Also inform whether the device is the same one sent to inputflinger for its layerstack.
+ // Prevent displays that are disabled from receiving input.
// TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
device.setDisplayFlagsLocked(t,
- device.getDisplayDeviceInfoLocked().touch != TOUCH_NONE
- ? SurfaceControl.DISPLAY_RECEIVES_INPUT : 0);
+ (isEnabled() && device.getDisplayDeviceInfoLocked().touch != TOUCH_NONE)
+ ? SurfaceControl.DISPLAY_RECEIVES_INPUT
+ : 0);
// Set the color mode and allowed display mode.
if (device == mPrimaryDisplayDevice) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 4a9ac70c7ef7..8cd35d506c97 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -4460,12 +4460,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
* a stylus deviceId is not already registered on device.
*/
@BinderThread
- @RequiresPermission(Manifest.permission.INJECT_EVENTS)
+ @EnforcePermission(Manifest.permission.INJECT_EVENTS)
@Override
public void addVirtualStylusIdForTestSession(IInputMethodClient client) {
- mContext.enforceCallingPermission(
- Manifest.permission.INJECT_EVENTS,
- "Using addVirtualStylusIdForTestSession() requires INJECT_EVENTS.");
int uid = Binder.getCallingUid();
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "addVirtualStylusIdForTestSession")) {
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index 84c7c5513319..da8992ae77f8 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -88,6 +88,7 @@ final class AppDataHelper {
* <p>
* <em>Note: To avoid a deadlock, do not call this method with {@code mLock} lock held</em>
*/
+ @GuardedBy("mPm.mInstallLock")
public void prepareAppDataAfterInstallLIF(AndroidPackage pkg) {
prepareAppDataPostCommitLIF(pkg, 0 /* previousAppId */);
}
@@ -97,6 +98,7 @@ final class AppDataHelper {
* {@link #prepareAppData(Installer.Batch, AndroidPackage, int, int, int)}
* @see #prepareAppDataAfterInstallLIF(AndroidPackage)
*/
+ @GuardedBy("mPm.mInstallLock")
public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
final PackageSetting ps;
synchronized (mPm.mLock) {
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 075fb47cceac..48ec436761e9 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -271,7 +271,7 @@ final class DeletePackageHelper {
// other processes clean up before deleting resources.
synchronized (mPm.mInstallLock) {
if (info.mArgs != null) {
- info.mArgs.doPostDeleteLI(true);
+ mRemovePackageHelper.cleanUpResources(info.mArgs);
}
boolean reEnableStub = false;
@@ -341,6 +341,7 @@ final class DeletePackageHelper {
/*
* This method handles package deletion in general
*/
+ @GuardedBy("mPm.mInstallLock")
public boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
boolean deleteCodeAndResources, @NonNull int[] allUserHandles, int flags,
PackageRemovedInfo outInfo, boolean writeSettings) {
@@ -393,8 +394,18 @@ final class DeletePackageHelper {
return new DeletePackageAction(ps, disabledPs, outInfo, flags, user);
}
+ public void executeDeletePackage(DeletePackageAction action, String packageName,
+ boolean deleteCodeAndResources, @NonNull int[] allUserHandles, boolean writeSettings)
+ throws SystemDeleteException {
+ synchronized (mPm.mInstallLock) {
+ executeDeletePackageLIF(action, packageName, deleteCodeAndResources, allUserHandles,
+ writeSettings);
+ }
+ }
+
/** Deletes a package. Only throws when install of a disabled package fails. */
- public void executeDeletePackageLIF(DeletePackageAction action,
+ @GuardedBy("mPm.mInstallLock")
+ private void executeDeletePackageLIF(DeletePackageAction action,
String packageName, boolean deleteCodeAndResources,
@NonNull int[] allUserHandles, boolean writeSettings) throws SystemDeleteException {
final PackageSetting ps = action.mDeletingPs;
@@ -487,7 +498,9 @@ final class DeletePackageHelper {
// Take a note whether we deleted the package for all users
if (outInfo != null) {
- outInfo.mRemovedForAllUsers = mPm.mPackages.get(ps.getPackageName()) == null;
+ synchronized (mPm.mLock) {
+ outInfo.mRemovedForAllUsers = mPm.mPackages.get(ps.getPackageName()) == null;
+ }
}
}
@@ -538,6 +551,7 @@ final class DeletePackageHelper {
}
}
+ @GuardedBy("mPm.mInstallLock")
private void deleteInstalledPackageLIF(PackageSetting ps,
boolean deleteCodeAndResources, int flags, @NonNull int[] allUserHandles,
PackageRemovedInfo outInfo, boolean writeSettings) {
@@ -556,7 +570,7 @@ final class DeletePackageHelper {
// Delete application code and resources only for parent packages
if (deleteCodeAndResources && (outInfo != null)) {
- outInfo.mArgs = new FileInstallArgs(
+ outInfo.mArgs = new InstallArgs(
ps.getPathString(), getAppDexInstructionSets(
ps.getPrimaryCpuAbi(), ps.getSecondaryCpuAbi()), mPm);
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.mArgs);
@@ -636,7 +650,10 @@ final class DeletePackageHelper {
flags |= PackageManager.DELETE_KEEP_DATA;
}
- deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo, writeSettings);
+ synchronized (mPm.mInstallLock) {
+ deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo,
+ writeSettings);
+ }
}
public void deletePackageVersionedInternal(VersionedPackage versionedPackage,
diff --git a/services/core/java/com/android/server/pm/FileInstallArgs.java b/services/core/java/com/android/server/pm/FileInstallArgs.java
deleted file mode 100644
index 4d9e2a311ce2..000000000000
--- a/services/core/java/com/android/server/pm/FileInstallArgs.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2021 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 com.android.server.pm;
-
-import static android.app.AppOpsManager.MODE_DEFAULT;
-import static android.content.pm.PackageManager.INSTALL_STAGED;
-import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-import static android.os.incremental.IncrementalManager.isIncrementalPath;
-
-import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
-import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
-import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
-import static com.android.server.pm.PackageManagerService.TAG;
-import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
-
-import android.content.pm.DataLoaderType;
-import android.content.pm.PackageInstaller;
-import android.content.pm.PackageManager;
-import android.content.pm.SigningDetails;
-import android.content.pm.parsing.ApkLiteParseUtils;
-import android.content.pm.parsing.PackageLite;
-import android.content.pm.parsing.result.ParseResult;
-import android.content.pm.parsing.result.ParseTypeImpl;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.SELinux;
-import android.os.Trace;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.Slog;
-
-import com.android.internal.content.NativeLibraryHelper;
-import com.android.server.pm.parsing.pkg.ParsedPackage;
-
-import libcore.io.IoUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Logic to handle installation of new applications, including copying
- * and renaming logic.
- */
-class FileInstallArgs extends InstallArgs {
- private File mCodeFile;
-
- // Example topology:
- // /data/app/com.example/base.apk
- // /data/app/com.example/split_foo.apk
- // /data/app/com.example/lib/arm/libfoo.so
- // /data/app/com.example/lib/arm64/libfoo.so
- // /data/app/com.example/dalvik/arm/base.apk@classes.dex
-
- /** New install */
- FileInstallArgs(InstallingSession params) {
- super(params);
- }
-
- /**
- * Create args that describe an existing installed package. Typically used
- * when cleaning up old installs, or used as a move source.
- */
- FileInstallArgs(String codePath, String[] instructionSets, PackageManagerService pm) {
- super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
- null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
- SigningDetails.UNKNOWN,
- PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,
- false, DataLoaderType.NONE,
- PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, pm);
- mCodeFile = (codePath != null) ? new File(codePath) : null;
- }
-
- int copyApk() {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
- try {
- return doCopyApk();
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
-
- private int doCopyApk() {
- if (mOriginInfo.mStaged) {
- if (DEBUG_INSTALL) Slog.d(TAG, mOriginInfo.mFile + " already staged; skipping copy");
- mCodeFile = mOriginInfo.mFile;
- return PackageManager.INSTALL_SUCCEEDED;
- }
-
- try {
- final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
- final File tempDir =
- mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral);
- mCodeFile = tempDir;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to create copy file: " + e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
-
- int ret = PackageManagerServiceUtils.copyPackage(
- mOriginInfo.mFile.getAbsolutePath(), mCodeFile);
- if (ret != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Failed to copy package");
- return ret;
- }
-
- final boolean isIncremental = isIncrementalPath(mCodeFile.getAbsolutePath());
- final File libraryRoot = new File(mCodeFile, LIB_DIR_NAME);
- NativeLibraryHelper.Handle handle = null;
- try {
- handle = NativeLibraryHelper.Handle.create(mCodeFile);
- ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
- mAbiOverride, isIncremental);
- } catch (IOException e) {
- Slog.e(TAG, "Copying native libraries failed", e);
- ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- } finally {
- IoUtils.closeQuietly(handle);
- }
-
- return ret;
- }
-
- int doPreInstall(int status) {
- if (status != PackageManager.INSTALL_SUCCEEDED) {
- cleanUp();
- }
- return status;
- }
-
- @Override
- boolean doRename(int status, ParsedPackage parsedPackage) {
- if (status != PackageManager.INSTALL_SUCCEEDED) {
- cleanUp();
- return false;
- }
-
- final File targetDir = resolveTargetDir();
- final File beforeCodeFile = mCodeFile;
- final File afterCodeFile = PackageManagerServiceUtils.getNextCodePath(targetDir,
- parsedPackage.getPackageName());
-
- if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
- final boolean onIncremental = mPm.mIncrementalManager != null
- && isIncrementalPath(beforeCodeFile.getAbsolutePath());
- try {
- makeDirRecursive(afterCodeFile.getParentFile(), 0775);
- if (onIncremental) {
- // Just link files here. The stage dir will be removed when the installation
- // session is completed.
- mPm.mIncrementalManager.linkCodePath(beforeCodeFile, afterCodeFile);
- } else {
- Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
- }
- } catch (IOException | ErrnoException e) {
- Slog.w(TAG, "Failed to rename", e);
- return false;
- }
-
- if (!onIncremental && !SELinux.restoreconRecursive(afterCodeFile)) {
- Slog.w(TAG, "Failed to restorecon");
- return false;
- }
-
- // Reflect the rename internally
- mCodeFile = afterCodeFile;
-
- // Reflect the rename in scanned details
- try {
- parsedPackage.setPath(afterCodeFile.getCanonicalPath());
- } catch (IOException e) {
- Slog.e(TAG, "Failed to get path: " + afterCodeFile, e);
- return false;
- }
- parsedPackage.setBaseApkPath(FileUtils.rewriteAfterRename(beforeCodeFile,
- afterCodeFile, parsedPackage.getBaseApkPath()));
- parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile,
- afterCodeFile, parsedPackage.getSplitCodePaths()));
-
- return true;
- }
-
- // TODO(b/168126411): Once staged install flow starts using the same folder as non-staged
- // flow, we won't need this method anymore.
- private File resolveTargetDir() {
- boolean isStagedInstall = (mInstallFlags & INSTALL_STAGED) != 0;
- if (isStagedInstall) {
- return Environment.getDataAppDirectory(null);
- } else {
- return mCodeFile.getParentFile();
- }
- }
-
- int doPostInstall(int status, int uid) {
- if (status != PackageManager.INSTALL_SUCCEEDED) {
- cleanUp();
- }
- return status;
- }
-
- @Override
- String getCodePath() {
- return (mCodeFile != null) ? mCodeFile.getAbsolutePath() : null;
- }
-
- private boolean cleanUp() {
- if (mCodeFile == null || !mCodeFile.exists()) {
- return false;
- }
- mRemovePackageHelper.removeCodePathLI(mCodeFile);
- return true;
- }
-
- void cleanUpResourcesLI() {
- // Try enumerating all code paths before deleting
- List<String> allCodePaths = Collections.EMPTY_LIST;
- if (mCodeFile != null && mCodeFile.exists()) {
- final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
- final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
- input.reset(), mCodeFile, /* flags */ 0);
- if (result.isSuccess()) {
- // Ignore error; we tried our best
- allCodePaths = result.getResult().getAllApkPaths();
- }
- }
-
- cleanUp();
- removeDexFiles(allCodePaths, mInstructionSets);
- }
-
- void removeDexFiles(List<String> allCodePaths, String[] instructionSets) {
- if (!allCodePaths.isEmpty()) {
- if (instructionSets == null) {
- throw new IllegalStateException("instructionSet == null");
- }
- String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
- for (String codePath : allCodePaths) {
- for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- try {
- mPm.mInstaller.rmdex(codePath, dexCodeInstructionSet);
- } catch (Installer.InstallerException ignored) {
- }
- }
- }
- }
- }
-
- boolean doPostDeleteLI(boolean delete) {
- // XXX err, shouldn't we respect the delete flag?
- cleanUpResourcesLI();
- return true;
- }
-}
diff --git a/services/core/java/com/android/server/pm/InstallArgs.java b/services/core/java/com/android/server/pm/InstallArgs.java
index fa8a9756c179..616bb8f419dd 100644
--- a/services/core/java/com/android/server/pm/InstallArgs.java
+++ b/services/core/java/com/android/server/pm/InstallArgs.java
@@ -16,19 +16,24 @@
package com.android.server.pm;
+import static android.app.AppOpsManager.MODE_DEFAULT;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.DataLoaderType;
import android.content.pm.IPackageInstallObserver2;
+import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.SigningDetails;
import android.os.UserHandle;
import com.android.internal.util.Preconditions;
-import com.android.server.pm.parsing.pkg.ParsedPackage;
+import java.io.File;
import java.util.List;
-abstract class InstallArgs {
+final class InstallArgs {
+ File mCodeFile;
/** @see InstallingSession#mOriginInfo */
final OriginInfo mOriginInfo;
/** @see InstallingSession#mMoveInfo */
@@ -108,28 +113,21 @@ abstract class InstallArgs {
params.mDataLoaderType, params.mPackageSource, params.mPm);
}
- abstract int copyApk();
- abstract int doPreInstall(int status);
-
/**
- * Rename package into final resting place. All paths on the given
- * scanned package should be updated to reflect the rename.
+ * Create args that describe an existing installed package. Typically used
+ * when cleaning up old installs, or used as a move source.
*/
- abstract boolean doRename(int status, ParsedPackage parsedPackage);
- abstract int doPostInstall(int status, int uid);
-
- /** @see PackageSettingBase#getPath() */
- abstract String getCodePath();
-
- // Need installer lock especially for dex file removal.
- abstract void cleanUpResourcesLI();
- abstract boolean doPostDeleteLI(boolean delete);
-
- protected boolean isEphemeral() {
- return (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+ InstallArgs(String codePath, String[] instructionSets, PackageManagerService pm) {
+ this(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
+ null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
+ SigningDetails.UNKNOWN, PackageManager.INSTALL_REASON_UNKNOWN,
+ PackageManager.INSTALL_SCENARIO_DEFAULT, false, DataLoaderType.NONE,
+ PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, pm);
+ mCodeFile = (codePath != null) ? new File(codePath) : null;
}
- UserHandle getUser() {
- return mUser;
+ /** @see PackageSettingBase#getPath() */
+ String getCodePath() {
+ return (mCodeFile != null) ? mCodeFile.getAbsolutePath() : null;
}
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index ee4434863a8b..8bb9b841e1a2 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -34,6 +34,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_UID_CHANGED;
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_RESTORE;
import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP;
+import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
@@ -89,6 +90,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures
import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
+import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
import android.annotation.NonNull;
@@ -123,9 +125,11 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SELinux;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
@@ -135,6 +139,8 @@ import android.os.incremental.IncrementalStorage;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.stats.storage.StorageEnums;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
@@ -236,7 +242,7 @@ final class InstallPackageHelper {
* This needs to be fixed so, once we get to this point, no errors are
* possible and the system is not left in an inconsistent state.
*/
- @GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
+ @GuardedBy("mPm.mLock")
public AndroidPackage commitReconciledScanResultLocked(
@NonNull ReconciledPackage reconciledPkg, int[] allUsers) {
final ScanResult result = reconciledPkg.mScanResult;
@@ -347,7 +353,7 @@ final class InstallPackageHelper {
|| (oldPkgSetting != null && oldPkgSetting.getUsesLibraryInfos() != null)) {
// Reconcile if the new package or the old package uses shared libraries.
// It is possible that the old package uses shared libraries but the new one doesn't.
- mSharedLibraries.executeSharedLibrariesUpdateLPw(pkg, pkgSetting, null, null,
+ mSharedLibraries.executeSharedLibrariesUpdate(pkg, pkgSetting, null, null,
reconciledPkg.mCollectedSharedLibraryInfos, allUsers);
}
@@ -365,8 +371,10 @@ final class InstallPackageHelper {
for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
final String codePathString = changedAbiCodePath.get(i);
try {
- mPm.mInstaller.rmdex(codePathString,
- getDexCodeInstructionSet(getPreferredInstructionSet()));
+ synchronized (mPm.mInstallLock) {
+ mPm.mInstaller.rmdex(codePathString,
+ getDexCodeInstructionSet(getPreferredInstructionSet()));
+ }
} catch (Installer.InstallerException ignored) {
}
}
@@ -405,30 +413,12 @@ final class InstallPackageHelper {
mPm.setPlatformPackage(pkg, pkgSetting);
}
- ArrayList<AndroidPackage> clientLibPkgs = null;
// writer
- synchronized (mPm.mLock) {
- if (!ArrayUtils.isEmpty(reconciledPkg.mAllowedSharedLibraryInfos)) {
- for (SharedLibraryInfo info : reconciledPkg.mAllowedSharedLibraryInfos) {
- mSharedLibraries.commitSharedLibraryInfoLPw(info);
- }
- final Map<String, AndroidPackage> combinedSigningDetails =
- reconciledPkg.getCombinedAvailablePackages();
- try {
- // Shared libraries for the package need to be updated.
- mSharedLibraries.updateSharedLibrariesLPw(pkg, pkgSetting, null, null,
- combinedSigningDetails);
- } catch (PackageManagerException e) {
- Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
- }
- // Update all applications that use this library. Skip when booting
- // since this will be done after all packages are scaned.
- if ((scanFlags & SCAN_BOOTING) == 0) {
- clientLibPkgs = mSharedLibraries.updateAllSharedLibrariesLPw(pkg, pkgSetting,
- combinedSigningDetails);
- }
- }
- }
+ ArrayList<AndroidPackage> clientLibPkgs =
+ mSharedLibraries.commitSharedLibraryChanges(pkg, pkgSetting,
+ reconciledPkg.mAllowedSharedLibraryInfos,
+ reconciledPkg.getCombinedAvailablePackages(), scanFlags);
+
if (reconciledPkg.mInstallResult != null) {
reconciledPkg.mInstallResult.mLibraryConsumers = clientLibPkgs;
}
@@ -795,126 +785,14 @@ final class InstallPackageHelper {
return false;
}
- public void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
- List<InstallRequest> apexInstallRequests = new ArrayList<>();
- List<InstallRequest> apkInstallRequests = new ArrayList<>();
- for (InstallRequest request : installRequests) {
- if ((request.mArgs.mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
- apexInstallRequests.add(request);
- } else {
- apkInstallRequests.add(request);
- }
- }
- // Note: supporting multi package install of both APEXes and APKs might requir some
- // thinking to ensure atomicity of the install.
- if (!apexInstallRequests.isEmpty() && !apkInstallRequests.isEmpty()) {
- // This should've been caught at the validation step, but for some reason wasn't.
- throw new IllegalStateException(
- "Attempted to do a multi package install of both APEXes and APKs");
- }
- if (!apexInstallRequests.isEmpty()) {
- if (success) {
- // Since installApexPackages requires talking to external service (apexd), we
- // schedule to run it async. Once it finishes, it will resume the install.
- Thread t = new Thread(() -> installApexPackagesTraced(apexInstallRequests),
- "installApexPackages");
- t.start();
- } else {
- // Non-staged APEX installation failed somewhere before
- // processInstallRequestAsync. In that case just notify the observer about the
- // failure.
- InstallRequest request = apexInstallRequests.get(0);
- mPm.notifyInstallObserver(request.mInstallResult,
- request.mArgs.mObserver);
- }
- return;
- }
-
- processApkInstallRequests(success, installRequests);
- }
-
- private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) {
- if (success) {
- for (InstallRequest request : installRequests) {
- request.mArgs.doPreInstall(request.mInstallResult.mReturnCode);
- }
- synchronized (mPm.mInstallLock) {
- installPackagesTracedLI(installRequests);
- }
- for (InstallRequest request : installRequests) {
- request.mArgs.doPostInstall(
- request.mInstallResult.mReturnCode, request.mInstallResult.mUid);
- }
- }
- for (InstallRequest request : installRequests) {
- restoreAndPostInstall(request.mArgs.mUser.getIdentifier(),
- request.mInstallResult,
- new PostInstallData(request.mArgs,
- request.mInstallResult, null));
- }
- }
-
- private void installApexPackagesTraced(List<InstallRequest> requests) {
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installApexPackages");
- installApexPackages(requests);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
-
- private void installApexPackages(List<InstallRequest> requests) {
- if (requests.isEmpty()) {
- return;
- }
- if (requests.size() != 1) {
- throw new IllegalStateException(
- "Only a non-staged install of a single APEX is supported");
- }
- InstallRequest request = requests.get(0);
- try {
- // Should directory scanning logic be moved to ApexManager for better test coverage?
- final File dir = request.mArgs.mOriginInfo.mResolvedFile;
- final File[] apexes = dir.listFiles();
- if (apexes == null) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- dir.getAbsolutePath() + " is not a directory");
- }
- if (apexes.length != 1) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Expected exactly one .apex file under " + dir.getAbsolutePath()
- + " got: " + apexes.length);
- }
- try (PackageParser2 packageParser = mPm.mInjector.getScanningPackageParser()) {
- ApexInfo apexInfo = mApexManager.installPackage(apexes[0]);
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- // APEX has been handled successfully by apexd. Let's continue the install flow
- // so it will be scanned and registered with the system.
- // TODO(b/225756739): Improve atomicity of rebootless APEX install.
- // The newly installed APEX will not be reverted even if
- // processApkInstallRequests() fails. Need a way to keep info stored in apexd
- // and PMS in sync in the face of install failures.
- request.mInstallResult.mApexInfo = apexInfo;
- mPm.mHandler.post(() -> processApkInstallRequests(true, requests));
- return;
- } else {
- mPm.mApexPackageInfo.notifyPackageInstalled(apexInfo, packageParser);
- }
+ void installPackagesTraced(List<InstallRequest> requests) {
+ synchronized (mPm.mInstallLock) {
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
+ installPackagesLI(requests);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
- } catch (PackageManagerException e) {
- request.mInstallResult.setError("APEX installation failed", e);
- }
- PackageManagerService.invalidatePackageInfoCache();
- mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver);
- }
-
- @GuardedBy("mPm.mInstallLock")
- private void installPackagesTracedLI(List<InstallRequest> requests) {
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
- installPackagesLI(requests);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
@@ -1010,11 +888,12 @@ final class InstallPackageHelper {
return;
}
}
- ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
- installResults, prepareResults,
- Collections.unmodifiableMap(mPm.mPackages), versionInfos);
- CommitRequest commitRequest = null;
+
+ CommitRequest commitRequest;
synchronized (mPm.mLock) {
+ ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
+ installResults, prepareResults,
+ Collections.unmodifiableMap(mPm.mPackages), versionInfos);
Map<String, ReconciledPackage> reconciledPackages;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
@@ -1039,7 +918,7 @@ final class InstallPackageHelper {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
- executePostCommitSteps(commitRequest);
+ executePostCommitStepsLIF(commitRequest);
} finally {
if (success) {
for (InstallRequest request : requests) {
@@ -1061,7 +940,7 @@ final class InstallPackageHelper {
.buildVerificationRootHashString(baseCodePath, splitCodePaths);
VerificationUtils.broadcastPackageVerified(verificationId, originUri,
PackageManager.VERIFICATION_ALLOW, rootHashString,
- args.mDataLoaderType, args.getUser(), mContext);
+ args.mDataLoaderType, args.mUser, mContext);
}
} else {
for (ScanResult result : preparedScans.values()) {
@@ -1288,7 +1167,7 @@ final class InstallPackageHelper {
// the package setting for the latest library version.
if (parsedPackage.isStaticSharedLibrary()) {
SharedLibraryInfo libraryInfo =
- mSharedLibraries.getLatestStaticSharedLibraVersionLPr(parsedPackage);
+ mSharedLibraries.getLatestStaticSharedLibraVersion(parsedPackage);
if (libraryInfo != null) {
signatureCheckPs = mPm.mSettings.getPackageLPr(libraryInfo.getPackageName());
}
@@ -1541,7 +1420,7 @@ final class InstallPackageHelper {
}
if (!isApex) {
- if (!args.doRename(res.mReturnCode, parsedPackage)) {
+ if (!doRenameLI(args, res.mReturnCode, parsedPackage)) {
throw new PrepareFailure(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
}
@@ -1805,6 +1684,82 @@ final class InstallPackageHelper {
}
}
+ /**
+ * Rename package into final resting place. All paths on the given
+ * scanned package should be updated to reflect the rename.
+ */
+ @GuardedBy("mPm.mInstallLock")
+ private boolean doRenameLI(InstallArgs args, int status, ParsedPackage parsedPackage) {
+ if (args.mMoveInfo != null) {
+ if (status != PackageManager.INSTALL_SUCCEEDED) {
+ mRemovePackageHelper.cleanUpForMoveInstall(args.mMoveInfo.mToUuid,
+ args.mMoveInfo.mPackageName, args.mMoveInfo.mFromCodePath);
+ return false;
+ }
+ return true;
+ }
+ // For file installations
+ if (status != PackageManager.INSTALL_SUCCEEDED) {
+ mRemovePackageHelper.removeCodePath(args.mCodeFile);
+ return false;
+ }
+
+ final File targetDir = resolveTargetDir(args);
+ final File beforeCodeFile = args.mCodeFile;
+ final File afterCodeFile = PackageManagerServiceUtils.getNextCodePath(targetDir,
+ parsedPackage.getPackageName());
+
+ if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
+ final boolean onIncremental = mPm.mIncrementalManager != null
+ && isIncrementalPath(beforeCodeFile.getAbsolutePath());
+ try {
+ makeDirRecursive(afterCodeFile.getParentFile(), 0775);
+ if (onIncremental) {
+ // Just link files here. The stage dir will be removed when the installation
+ // session is completed.
+ mPm.mIncrementalManager.linkCodePath(beforeCodeFile, afterCodeFile);
+ } else {
+ Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
+ }
+ } catch (IOException | ErrnoException e) {
+ Slog.w(TAG, "Failed to rename", e);
+ return false;
+ }
+
+ if (!onIncremental && !SELinux.restoreconRecursive(afterCodeFile)) {
+ Slog.w(TAG, "Failed to restorecon");
+ return false;
+ }
+
+ // Reflect the rename internally
+ args.mCodeFile = afterCodeFile;
+
+ // Reflect the rename in scanned details
+ try {
+ parsedPackage.setPath(afterCodeFile.getCanonicalPath());
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to get path: " + afterCodeFile, e);
+ return false;
+ }
+ parsedPackage.setBaseApkPath(FileUtils.rewriteAfterRename(beforeCodeFile,
+ afterCodeFile, parsedPackage.getBaseApkPath()));
+ parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile,
+ afterCodeFile, parsedPackage.getSplitCodePaths()));
+
+ return true;
+ }
+
+ // TODO(b/168126411): Once staged install flow starts using the same folder as non-staged
+ // flow, we won't need this method anymore.
+ private File resolveTargetDir(InstallArgs args) {
+ boolean isStagedInstall = (args.mInstallFlags & INSTALL_STAGED) != 0;
+ if (isStagedInstall) {
+ return Environment.getDataAppDirectory(null);
+ } else {
+ return args.mCodeFile.getParentFile();
+ }
+ }
+
/*
* Cannot properly check CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS using CompatChanges
* as this only works for packages that are installed
@@ -1902,7 +1857,6 @@ final class InstallPackageHelper {
}
}
- final String packageName = pkg.getPackageName();
for (Map.Entry<String, String> entry : fsverityCandidates.entrySet()) {
final String filePath = entry.getKey();
final String signaturePath = entry.getValue();
@@ -1973,12 +1927,12 @@ final class InstallPackageHelper {
mPm.mSettings.getPackagesLocked());
if (reconciledPkg.mPrepareResult.mSystem) {
// Remove existing system package
- removePackageHelper.removePackageLI(oldPackage, true);
+ removePackageHelper.removePackage(oldPackage, true);
if (!disableSystemPackageLPw(oldPackage)) {
// We didn't need to disable the .apk as a current system package,
// which means we are replacing another update that is already
// installed. We need to make sure to delete the older one's .apk.
- res.mRemovedInfo.mArgs = new FileInstallArgs(
+ res.mRemovedInfo.mArgs = new InstallArgs(
oldPackage.getPath(),
getAppDexInstructionSets(
AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
@@ -1991,7 +1945,7 @@ final class InstallPackageHelper {
} else {
try {
// Settings will be written during the call to updateSettingsLI().
- deletePackageHelper.executeDeletePackageLIF(
+ deletePackageHelper.executeDeletePackage(
reconciledPkg.mDeletePackageAction, packageName,
true, request.mAllUsers, false);
} catch (SystemDeleteException e) {
@@ -2261,7 +2215,8 @@ final class InstallPackageHelper {
* is released. These are typically more expensive or require calls to installd, which often
* locks on {@link com.android.server.pm.PackageManagerService.mLock}.
*/
- private void executePostCommitSteps(CommitRequest commitRequest) {
+ @GuardedBy("mPm.mInstallLock")
+ private void executePostCommitStepsLIF(CommitRequest commitRequest) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
for (ReconciledPackage reconciledPkg : commitRequest.mReconciledPackages.values()) {
final boolean instantApp = ((reconciledPkg.mScanResult.mRequest.mScanFlags
@@ -2652,9 +2607,7 @@ final class InstallPackageHelper {
// Remove the update failed package's older resources safely now
InstallArgs args = res.mRemovedInfo != null ? res.mRemovedInfo.mArgs : null;
if (args != null) {
- synchronized (mPm.mInstallLock) {
- args.doPostDeleteLI(true);
- }
+ mRemovePackageHelper.cleanUpResources(args);
}
mPm.notifyInstallObserver(res, installObserver);
return;
@@ -2892,9 +2845,7 @@ final class InstallPackageHelper {
// ApplicationInfo changes have propagated to all application threads.
mPm.scheduleDeferredNoKillPostDelete(args);
} else {
- synchronized (mPm.mInstallLock) {
- args.doPostDeleteLI(true);
- }
+ mRemovePackageHelper.cleanUpResources(args);
}
} else {
// Force a gc to clear up things. Ask for a background one, it's fine to go on
@@ -3028,7 +2979,7 @@ final class InstallPackageHelper {
mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
synchronized (mPm.mLock) {
try {
- mSharedLibraries.updateSharedLibrariesLPw(
+ mSharedLibraries.updateSharedLibraries(
pkg, stubPkgSetting, null, null,
Collections.unmodifiableMap(mPm.mPackages));
} catch (PackageManagerException e) {
@@ -3100,14 +3051,14 @@ final class InstallPackageHelper {
mPm.mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/);
}
final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
- removePackageHelper.removePackageLI(stubPkg, true /*chatty*/);
+ removePackageHelper.removePackage(stubPkg, true /*chatty*/);
try {
return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, null);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(),
e);
// Remove the failed install
- removePackageHelper.removeCodePathLI(scanFile);
+ removePackageHelper.removeCodePath(scanFile);
throw e;
}
}
@@ -3150,7 +3101,7 @@ final class InstallPackageHelper {
if (!dstCodePath.exists()) {
return null;
}
- new RemovePackageHelper(mPm).removeCodePathLI(dstCodePath);
+ new RemovePackageHelper(mPm).removeCodePath(dstCodePath);
return null;
}
@@ -3236,16 +3187,16 @@ final class InstallPackageHelper {
final AndroidPackage pkg = scanSystemPackageTracedLI(
codePath, parseFlags, scanFlags, null);
- PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
-
- try {
- // update shared libraries for the newly re-installed system package
- mSharedLibraries.updateSharedLibrariesLPw(pkg, pkgSetting, null, null,
- Collections.unmodifiableMap(mPm.mPackages));
- } catch (PackageManagerException e) {
- Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
+ synchronized (mPm.mLock) {
+ PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
+ try {
+ // update shared libraries for the newly re-installed system package
+ mSharedLibraries.updateSharedLibraries(pkg, pkgSetting, null, null,
+ Collections.unmodifiableMap(mPm.mPackages));
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
+ }
}
-
mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
setPackageInstalledForSystemPackage(pkg, allUserHandles, origUserHandles, writeSettings);
@@ -3348,7 +3299,7 @@ final class InstallPackageHelper {
+ ", versionCode=" + ps.getVersionCode()
+ "; scanned versionCode="
+ scannedPkg.getLongVersionCode());
- mRemovePackageHelper.removePackageLI(scannedPkg, true);
+ mRemovePackageHelper.removePackage(scannedPkg, true);
expectingBetter.put(ps.getPackageName(), ps.getPath());
}
@@ -3358,7 +3309,7 @@ final class InstallPackageHelper {
if (disabledPs == null) {
logCriticalInfo(Log.WARN, "System package " + packageName
+ " no longer exists; its data will be wiped");
- mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false);
+ mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false);
} else {
// we still have a disabled system package, but, it still might have
// been removed. check the code path still exists and check there's
@@ -3409,10 +3360,12 @@ final class InstallPackageHelper {
// remove the package from the system and re-scan it without any
// special privileges
- mRemovePackageHelper.removePackageLI(pkg, true);
+ mRemovePackageHelper.removePackage(pkg, true);
try {
final File codePath = new File(pkg.getPath());
- scanSystemPackageTracedLI(codePath, 0, scanFlags, null);
+ synchronized (mPm.mInstallLock) {
+ scanSystemPackageTracedLI(codePath, 0, scanFlags, null);
+ }
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse updated, ex-system package: "
+ e.getMessage());
@@ -3425,7 +3378,7 @@ final class InstallPackageHelper {
// partition], completely remove the package data.
final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
if (ps != null && mPm.mPackages.get(packageName) == null) {
- mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false);
+ mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false);
}
logCriticalInfo(Log.WARN, msg);
}
@@ -3586,7 +3539,7 @@ final class InstallPackageHelper {
&& errorCode != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.WARN,
"Deleting invalid package at " + parseResult.scanFile);
- mRemovePackageHelper.removeCodePathLI(parseResult.scanFile);
+ mRemovePackageHelper.removeCodePath(parseResult.scanFile);
}
}
}
@@ -3622,11 +3575,13 @@ final class InstallPackageHelper {
mPm.mSettings.enableSystemPackageLPw(packageName);
try {
- final AndroidPackage newPkg = scanSystemPackageTracedLI(
- scanFile, reparseFlags, rescanFlags, null);
- // We rescanned a stub, add it to the list of stubbed system packages
- if (newPkg.isStub()) {
- stubSystemApps.add(packageName);
+ synchronized (mPm.mInstallLock) {
+ final AndroidPackage newPkg = scanSystemPackageTracedLI(
+ scanFile, reparseFlags, rescanFlags, null);
+ // We rescanned a stub, add it to the list of stubbed system packages
+ if (newPkg.isStub()) {
+ stubSystemApps.add(packageName);
+ }
}
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
@@ -3639,7 +3594,7 @@ final class InstallPackageHelper {
* Traces a package scan.
* @see #scanSystemPackageLI(File, int, int, UserHandle)
*/
- @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ @GuardedBy("mPm.mInstallLock")
public AndroidPackage scanSystemPackageTracedLI(File scanFile, final int parseFlags,
int scanFlags, UserHandle user) throws PackageManagerException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
@@ -3654,7 +3609,7 @@ final class InstallPackageHelper {
* Scans a package and returns the newly parsed package.
* Returns {@code null} in case of errors and the error code is stored in mLastScanError
*/
- @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ @GuardedBy("mPm.mInstallLock")
private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags,
UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
@@ -3688,7 +3643,7 @@ final class InstallPackageHelper {
* structures and the package is made available to the rest of the system.
* <p>NOTE: The return value should be removed. It's the passed in package object.
*/
- @GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
+ @GuardedBy("mPm.mInstallLock")
private AndroidPackage addForInitLI(ParsedPackage parsedPackage,
@ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags,
@@ -3770,11 +3725,13 @@ final class InstallPackageHelper {
// iff we've acquired an app ID for a new package setting, remove it so that it can be
// acquired by another request.
if (result.mPkgSetting.getAppId() > 0) {
- mPm.mSettings.removeAppIdLPw(result.mPkgSetting.getAppId());
+ synchronized (mPm.mLock) {
+ mPm.mSettings.removeAppIdLPw(result.mPkgSetting.getAppId());
+ }
}
}
- @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ @GuardedBy("mPm.mInstallLock")
private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage,
final @ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags, long currentTime,
@@ -3856,7 +3813,7 @@ final class InstallPackageHelper {
realPkgName, parseFlags, scanFlags, isPlatformPackage, user, cpuAbiOverride);
}
- @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ @GuardedBy("mPm.mInstallLock")
private ScanResult scanPackageNewLI(@NonNull ParsedPackage parsedPackage,
final @ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags, long currentTime,
@@ -3893,6 +3850,7 @@ final class InstallPackageHelper {
}
}
+ @GuardedBy("mPm.mInstallLock")
private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage,
@ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags,
@@ -3975,10 +3933,10 @@ final class InstallPackageHelper {
+ "; " + pkgSetting.getPathString()
+ " --> " + parsedPackage.getPath());
- final InstallArgs args = new FileInstallArgs(
+ final InstallArgs args = new InstallArgs(
pkgSetting.getPathString(), getAppDexInstructionSets(
pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()), mPm);
- args.cleanUpResourcesLI();
+ mRemovePackageHelper.cleanUpResources(args);
synchronized (mPm.mLock) {
mPm.mSettings.enableSystemPackageLPw(pkgSetting.getPackageName());
}
@@ -4060,13 +4018,11 @@ final class InstallPackageHelper {
+ parsedPackage.getLongVersionCode()
+ "; " + pkgSetting.getPathString() + " --> "
+ parsedPackage.getPath());
- InstallArgs args = new FileInstallArgs(
+ InstallArgs args = new InstallArgs(
pkgSetting.getPathString(), getAppDexInstructionSets(
pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()),
mPm);
- synchronized (mPm.mInstallLock) {
- args.cleanUpResourcesLI();
- }
+ mRemovePackageHelper.cleanUpResources(args);
} else {
// The application on /system is older than the application on /data. Hide
// the application on /system and the version on /data will be scanned later
@@ -4091,7 +4047,6 @@ final class InstallPackageHelper {
* Returns if forced apk verification can be skipped for the whole package, including splits.
*/
private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
- final String packageName = pkg.getPackageName();
if (!VerityUtils.hasFsverity(pkg.getBaseApkPath())) {
return false;
}
@@ -4398,8 +4353,10 @@ final class InstallPackageHelper {
// signed with the platform certificate. Check this in increasing order of
// computational cost.
if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) {
- final PackageSetting platformPkgSetting =
- mPm.mSettings.getPackageLPr("android");
+ final PackageSetting platformPkgSetting;
+ synchronized (mPm.mLock) {
+ platformPkgSetting = mPm.mSettings.getPackageLPr("android");
+ }
if (!comparePackageSignatures(platformPkgSetting,
pkg.getSigningDetails().getSignatures())) {
throw new PackageManagerException("Overlay "
@@ -4417,8 +4374,10 @@ final class InstallPackageHelper {
// SystemConfig is set, check this here to augment the last line of defense
// which is OMS.
if (pkg.getOverlayTargetOverlayableName() == null) {
- final PackageSetting targetPkgSetting =
- mPm.mSettings.getPackageLPr(pkg.getOverlayTarget());
+ final PackageSetting targetPkgSetting;
+ synchronized (mPm.mLock) {
+ targetPkgSetting = mPm.mSettings.getPackageLPr(pkg.getOverlayTarget());
+ }
if (targetPkgSetting != null) {
if (!comparePackageSignatures(targetPkgSetting,
pkg.getSigningDetails().getSignatures())) {
@@ -4430,9 +4389,11 @@ final class InstallPackageHelper {
+ " different certificates, and the overlay lacks"
+ " <overlay android:targetName>");
}
- final PackageSetting refPkgSetting =
- mPm.mSettings.getPackageLPr(
- mPm.mOverlayConfigSignaturePackage);
+ final PackageSetting refPkgSetting;
+ synchronized (mPm.mLock) {
+ refPkgSetting = mPm.mSettings.getPackageLPr(
+ mPm.mOverlayConfigSignaturePackage);
+ }
if (!comparePackageSignatures(refPkgSetting,
pkg.getSigningDetails().getSignatures())) {
throw new PackageManagerException("Overlay "
@@ -4452,13 +4413,18 @@ final class InstallPackageHelper {
if (!pkg.isPrivileged() && (pkg.getSharedUserId() != null)) {
SharedUserSetting sharedUserSetting = null;
try {
- sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(),
- 0, 0, false);
+ synchronized (mPm.mLock) {
+ sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(),
+ 0, 0, false);
+ }
} catch (PackageManagerException ignore) {
}
if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
// Exempt SharedUsers signed with the platform key.
- PackageSetting platformPkgSetting = mPm.mSettings.getPackageLPr("android");
+ final PackageSetting platformPkgSetting;
+ synchronized (mPm.mLock) {
+ platformPkgSetting = mPm.mSettings.getPackageLPr("android");
+ }
if (!comparePackageSignatures(platformPkgSetting,
pkg.getSigningDetails().getSignatures())) {
throw new PackageManagerException("Apps that share a user with a "
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index b3e039e5374b..0630ccdbf6e3 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -17,17 +17,21 @@
package com.android.server.pm;
import static android.app.AppOpsManager.MODE_DEFAULT;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.incremental.IncrementalManager.isIncrementalPath;
+import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTANT;
import static com.android.server.pm.PackageManagerService.TAG;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.apex.ApexInfo;
import android.content.pm.DataLoaderType;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.PackageInfoLite;
@@ -35,19 +39,28 @@ import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.SigningDetails;
import android.content.pm.parsing.PackageLite;
+import android.os.Environment;
import android.os.Trace;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.Pair;
import android.util.Slog;
import com.android.internal.content.F2fsUtils;
import com.android.internal.content.InstallLocationUtils;
+import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.util.Preconditions;
+import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import libcore.io.IoUtils;
+
import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
class InstallingSession {
final OriginInfo mOriginInfo;
@@ -79,6 +92,7 @@ class InstallingSession {
@NonNull
final PackageManagerService mPm;
final InstallPackageHelper mInstallPackageHelper;
+ final RemovePackageHelper mRemovePackageHelper;
InstallingSession(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
int installFlags, InstallSource installSource, String volumeUuid,
@@ -87,6 +101,7 @@ class InstallingSession {
mPm = pm;
mUser = user;
mInstallPackageHelper = new InstallPackageHelper(mPm);
+ mRemovePackageHelper = new RemovePackageHelper(mPm);
mOriginInfo = originInfo;
mMoveInfo = moveInfo;
mObserver = observer;
@@ -115,6 +130,7 @@ class InstallingSession {
mPm = pm;
mUser = user;
mInstallPackageHelper = new InstallPackageHelper(mPm);
+ mRemovePackageHelper = new RemovePackageHelper(mPm);
mOriginInfo = OriginInfo.fromStagedFile(stagedDir);
mMoveInfo = null;
mInstallReason = fixUpInstallReason(
@@ -195,7 +211,7 @@ class InstallingSession {
* policy if needed and then create install arguments based
* on the install location.
*/
- public void handleStartCopy() {
+ private void handleStartCopy() {
if ((mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
mRet = INSTALL_SUCCEEDED;
return;
@@ -232,14 +248,14 @@ class InstallingSession {
pkgLite.installLocation);
}
- void handleReturnCode() {
+ private void handleReturnCode() {
processPendingInstall();
}
private void processPendingInstall() {
- InstallArgs args = createInstallArgs(this);
+ InstallArgs args = new InstallArgs(this);
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
- mRet = args.copyApk();
+ mRet = copyApk(args);
}
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
F2fsUtils.releaseCompressedBlocks(
@@ -250,18 +266,89 @@ class InstallingSession {
} else {
PackageInstalledInfo res = new PackageInstalledInfo(mRet);
// Queue up an async operation since the package installation may take a little while.
- mPm.mHandler.post(() -> mInstallPackageHelper.processInstallRequests(
+ mPm.mHandler.post(() -> processInstallRequests(
res.mReturnCode == PackageManager.INSTALL_SUCCEEDED /* success */,
Collections.singletonList(new InstallRequest(args, res))));
}
}
- private InstallArgs createInstallArgs(InstallingSession installingSession) {
- if (installingSession.mMoveInfo != null) {
- return new MoveInstallArgs(installingSession);
+ private int copyApk(InstallArgs args) {
+ if (mMoveInfo == null) {
+ return copyApkForFileInstall(args);
} else {
- return new FileInstallArgs(installingSession);
+ return copyApkForMoveInstall(args);
+ }
+ }
+
+ private int copyApkForFileInstall(InstallArgs args) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
+ try {
+ if (mOriginInfo.mStaged) {
+ if (DEBUG_INSTALL) {
+ Slog.d(TAG, mOriginInfo.mFile + " already staged; skipping copy");
+ }
+ args.mCodeFile = mOriginInfo.mFile;
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
+ try {
+ final boolean isEphemeral =
+ (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+ args.mCodeFile =
+ mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to create copy file: " + e);
+ return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+
+ int ret = PackageManagerServiceUtils.copyPackage(
+ mOriginInfo.mFile.getAbsolutePath(), args.mCodeFile);
+ if (ret != PackageManager.INSTALL_SUCCEEDED) {
+ Slog.e(TAG, "Failed to copy package");
+ return ret;
+ }
+
+ final boolean isIncremental = isIncrementalPath(args.mCodeFile.getAbsolutePath());
+ final File libraryRoot = new File(args.mCodeFile, LIB_DIR_NAME);
+ NativeLibraryHelper.Handle handle = null;
+ try {
+ handle = NativeLibraryHelper.Handle.create(args.mCodeFile);
+ ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
+ args.mAbiOverride, isIncremental);
+ } catch (IOException e) {
+ Slog.e(TAG, "Copying native libraries failed", e);
+ ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ } finally {
+ IoUtils.closeQuietly(handle);
+ }
+
+ return ret;
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ private int copyApkForMoveInstall(InstallArgs args) {
+ if (DEBUG_INSTALL) {
+ Slog.d(TAG, "Moving " + mMoveInfo.mPackageName + " from "
+ + mMoveInfo.mFromUuid + " to " + mMoveInfo.mToUuid);
}
+ synchronized (mPm.mInstallLock) {
+ try {
+ mPm.mInstaller.moveCompleteApp(mMoveInfo.mFromUuid, mMoveInfo.mToUuid,
+ mMoveInfo.mPackageName, mMoveInfo.mAppId, mMoveInfo.mSeInfo,
+ mMoveInfo.mTargetSdkVersion, mMoveInfo.mFromCodePath);
+ } catch (Installer.InstallerException e) {
+ Slog.w(TAG, "Failed to move app", e);
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ }
+ }
+
+ final String toPathName = new File(mMoveInfo.mFromCodePath).getName();
+ args.mCodeFile = new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName);
+ if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + args.mCodeFile);
+
+ return PackageManager.INSTALL_SUCCEEDED;
}
/**
@@ -368,4 +455,217 @@ class InstallingSession {
private void setTraceCookie(int traceCookie) {
mTraceCookie = traceCookie;
}
+
+ private void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
+ List<InstallRequest> apexInstallRequests = new ArrayList<>();
+ List<InstallRequest> apkInstallRequests = new ArrayList<>();
+ for (InstallRequest request : installRequests) {
+ if ((request.mArgs.mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
+ apexInstallRequests.add(request);
+ } else {
+ apkInstallRequests.add(request);
+ }
+ }
+ // Note: supporting multi package install of both APEXes and APKs might requir some
+ // thinking to ensure atomicity of the install.
+ if (!apexInstallRequests.isEmpty() && !apkInstallRequests.isEmpty()) {
+ // This should've been caught at the validation step, but for some reason wasn't.
+ throw new IllegalStateException(
+ "Attempted to do a multi package install of both APEXes and APKs");
+ }
+ if (!apexInstallRequests.isEmpty()) {
+ if (success) {
+ // Since installApexPackages requires talking to external service (apexd), we
+ // schedule to run it async. Once it finishes, it will resume the install.
+ Thread t = new Thread(() -> installApexPackagesTraced(apexInstallRequests),
+ "installApexPackages");
+ t.start();
+ } else {
+ // Non-staged APEX installation failed somewhere before
+ // processInstallRequestAsync. In that case just notify the observer about the
+ // failure.
+ InstallRequest request = apexInstallRequests.get(0);
+ mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver);
+ }
+ return;
+ }
+
+ processApkInstallRequests(success, installRequests);
+ }
+
+ private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) {
+ if (success) {
+ for (InstallRequest request : installRequests) {
+ if (request.mInstallResult.mReturnCode != PackageManager.INSTALL_SUCCEEDED) {
+ cleanUpForFailedInstall(request.mArgs);
+ }
+ }
+
+ mInstallPackageHelper.installPackagesTraced(installRequests);
+
+ for (InstallRequest request : installRequests) {
+ doPostInstall(request.mInstallResult.mReturnCode, request.mArgs);
+ }
+ }
+ for (InstallRequest request : installRequests) {
+ mInstallPackageHelper.restoreAndPostInstall(request.mArgs.mUser.getIdentifier(),
+ request.mInstallResult,
+ new PostInstallData(request.mArgs,
+ request.mInstallResult, null));
+ }
+ }
+
+ private void doPostInstall(int status, InstallArgs args) {
+ if (mMoveInfo != null) {
+ if (status == PackageManager.INSTALL_SUCCEEDED) {
+ mRemovePackageHelper.cleanUpForMoveInstall(mMoveInfo.mFromUuid,
+ mMoveInfo.mPackageName, mMoveInfo.mFromCodePath);
+ } else {
+ mRemovePackageHelper.cleanUpForMoveInstall(mMoveInfo.mToUuid,
+ mMoveInfo.mPackageName, mMoveInfo.mFromCodePath);
+ }
+ } else {
+ if (status != PackageManager.INSTALL_SUCCEEDED) {
+ mRemovePackageHelper.removeCodePath(args.mCodeFile);
+ }
+ }
+ }
+
+ private void cleanUpForFailedInstall(InstallArgs args) {
+ if (args.mMoveInfo != null) {
+ mRemovePackageHelper.cleanUpForMoveInstall(args.mMoveInfo.mToUuid,
+ args.mMoveInfo.mPackageName, args.mMoveInfo.mFromCodePath);
+ } else {
+ mRemovePackageHelper.removeCodePath(args.mCodeFile);
+ }
+ }
+
+ private void installApexPackagesTraced(List<InstallRequest> requests) {
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installApexPackages");
+ installApexPackages(requests);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ private void installApexPackages(List<InstallRequest> requests) {
+ if (requests.isEmpty()) {
+ return;
+ }
+ if (requests.size() != 1) {
+ throw new IllegalStateException(
+ "Only a non-staged install of a single APEX is supported");
+ }
+ InstallRequest request = requests.get(0);
+ try {
+ // Should directory scanning logic be moved to ApexManager for better test coverage?
+ final File dir = request.mArgs.mOriginInfo.mResolvedFile;
+ final File[] apexes = dir.listFiles();
+ if (apexes == null) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ dir.getAbsolutePath() + " is not a directory");
+ }
+ if (apexes.length != 1) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Expected exactly one .apex file under " + dir.getAbsolutePath()
+ + " got: " + apexes.length);
+ }
+ try (PackageParser2 packageParser = mPm.mInjector.getScanningPackageParser()) {
+ ApexInfo apexInfo = mPm.mApexManager.installPackage(apexes[0]);
+ if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
+ // APEX has been handled successfully by apexd. Let's continue the install flow
+ // so it will be scanned and registered with the system.
+ // TODO(b/225756739): Improve atomicity of rebootless APEX install.
+ // The newly installed APEX will not be reverted even if
+ // processApkInstallRequests() fails. Need a way to keep info stored in apexd
+ // and PMS in sync in the face of install failures.
+ request.mInstallResult.mApexInfo = apexInfo;
+ mPm.mHandler.post(() -> processApkInstallRequests(true, requests));
+ return;
+ } else {
+ mPm.mApexPackageInfo.notifyPackageInstalled(apexInfo, packageParser);
+ }
+ }
+ } catch (PackageManagerException e) {
+ request.mInstallResult.setError("APEX installation failed", e);
+ }
+ PackageManagerService.invalidatePackageInfoCache();
+ mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver);
+ }
+
+ /**
+ * Container for a multi-package install which refers to all install sessions and args being
+ * committed together.
+ */
+ private class MultiPackageInstallingSession {
+ private final List<InstallingSession> mChildInstallingSessions;
+ private final Map<InstallArgs, Integer> mCurrentState;
+ @NonNull
+ final PackageManagerService mPm;
+ final UserHandle mUser;
+
+ MultiPackageInstallingSession(UserHandle user,
+ List<InstallingSession> childInstallingSessions,
+ PackageManagerService pm)
+ throws PackageManagerException {
+ if (childInstallingSessions.size() == 0) {
+ throw new PackageManagerException("No child sessions found!");
+ }
+ mPm = pm;
+ mUser = user;
+ mChildInstallingSessions = childInstallingSessions;
+ for (int i = 0; i < childInstallingSessions.size(); i++) {
+ final InstallingSession childInstallingSession = childInstallingSessions.get(i);
+ childInstallingSession.mParentInstallingSession = this;
+ }
+ this.mCurrentState = new ArrayMap<>(mChildInstallingSessions.size());
+ }
+
+ public void start() {
+ if (DEBUG_INSTALL) Slog.i(TAG, "start " + mUser + ": " + this);
+ Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
+ System.identityHashCode(this));
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "start");
+ for (InstallingSession childInstallingSession : mChildInstallingSessions) {
+ childInstallingSession.handleStartCopy();
+ }
+ for (InstallingSession childInstallingSession : mChildInstallingSessions) {
+ childInstallingSession.handleReturnCode();
+ }
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+
+ public void tryProcessInstallRequest(InstallArgs args, int currentStatus) {
+ mCurrentState.put(args, currentStatus);
+ if (mCurrentState.size() != mChildInstallingSessions.size()) {
+ return;
+ }
+ int completeStatus = PackageManager.INSTALL_SUCCEEDED;
+ for (Integer status : mCurrentState.values()) {
+ if (status == PackageManager.INSTALL_UNKNOWN) {
+ return;
+ } else if (status != PackageManager.INSTALL_SUCCEEDED) {
+ completeStatus = status;
+ break;
+ }
+ }
+ final List<InstallRequest> installRequests = new ArrayList<>(mCurrentState.size());
+ for (Map.Entry<InstallArgs, Integer> entry : mCurrentState.entrySet()) {
+ installRequests.add(new InstallRequest(entry.getKey(),
+ new PackageInstalledInfo(completeStatus)));
+ }
+ int finalCompleteStatus = completeStatus;
+ mPm.mHandler.post(() -> processInstallRequests(
+ finalCompleteStatus == PackageManager.INSTALL_SUCCEEDED /* success */,
+ installRequests));
+ }
+
+ @Override
+ public String toString() {
+ return "MultiPackageInstallingSession{" + Integer.toHexString(
+ System.identityHashCode(this))
+ + "}";
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/MoveInstallArgs.java b/services/core/java/com/android/server/pm/MoveInstallArgs.java
deleted file mode 100644
index 1f167ce2ec9a..000000000000
--- a/services/core/java/com/android/server/pm/MoveInstallArgs.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2021 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 com.android.server.pm;
-
-import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
-import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
-
-import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
-import static com.android.server.pm.PackageManagerService.TAG;
-
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.util.Slog;
-
-import com.android.server.pm.parsing.pkg.ParsedPackage;
-
-import java.io.File;
-
-/**
- * Logic to handle movement of existing installed applications.
- */
-final class MoveInstallArgs extends InstallArgs {
- private File mCodeFile;
-
- /** New install */
- MoveInstallArgs(InstallingSession params) {
- super(params);
- }
-
- int copyApk() {
- if (DEBUG_INSTALL) {
- Slog.d(TAG, "Moving " + mMoveInfo.mPackageName + " from "
- + mMoveInfo.mFromUuid + " to " + mMoveInfo.mToUuid);
- }
- synchronized (mPm.mInstaller) {
- try {
- mPm.mInstaller.moveCompleteApp(mMoveInfo.mFromUuid, mMoveInfo.mToUuid,
- mMoveInfo.mPackageName, mMoveInfo.mAppId, mMoveInfo.mSeInfo,
- mMoveInfo.mTargetSdkVersion, mMoveInfo.mFromCodePath);
- } catch (Installer.InstallerException e) {
- Slog.w(TAG, "Failed to move app", e);
- return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- }
- }
-
- final String toPathName = new File(mMoveInfo.mFromCodePath).getName();
- mCodeFile = new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName);
- if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + mCodeFile);
-
- return PackageManager.INSTALL_SUCCEEDED;
- }
-
- int doPreInstall(int status) {
- if (status != PackageManager.INSTALL_SUCCEEDED) {
- cleanUp(mMoveInfo.mToUuid);
- }
- return status;
- }
-
- @Override
- boolean doRename(int status, ParsedPackage parsedPackage) {
- if (status != PackageManager.INSTALL_SUCCEEDED) {
- cleanUp(mMoveInfo.mToUuid);
- return false;
- }
-
- return true;
- }
-
- int doPostInstall(int status, int uid) {
- if (status == PackageManager.INSTALL_SUCCEEDED) {
- cleanUp(mMoveInfo.mFromUuid);
- } else {
- cleanUp(mMoveInfo.mToUuid);
- }
- return status;
- }
-
- @Override
- String getCodePath() {
- return (mCodeFile != null) ? mCodeFile.getAbsolutePath() : null;
- }
-
- private void cleanUp(String volumeUuid) {
- final String toPathName = new File(mMoveInfo.mFromCodePath).getName();
- final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid),
- toPathName);
- Slog.d(TAG, "Cleaning up " + mMoveInfo.mPackageName + " on " + volumeUuid);
- final int[] userIds = mPm.mUserManager.getUserIds();
- synchronized (mPm.mInstallLock) {
- // Clean up both app data and code
- // All package moves are frozen until finished
-
- // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since
- // this task was only focused on moving data on internal storage.
- // We don't want ART profiles cleared, because they don't move,
- // so we would be deleting the only copy (b/149200535).
- final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE
- | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
- for (int userId : userIds) {
- try {
- mPm.mInstaller.destroyAppData(volumeUuid, mMoveInfo.mPackageName, userId, flags,
- 0);
- } catch (Installer.InstallerException e) {
- Slog.w(TAG, String.valueOf(e));
- }
- }
- mRemovePackageHelper.removeCodePathLI(codeFile);
- }
- }
-
- void cleanUpResourcesLI() {
- throw new UnsupportedOperationException();
- }
-
- boolean doPostDeleteLI(boolean delete) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/services/core/java/com/android/server/pm/MultiPackageInstallingSession.java b/services/core/java/com/android/server/pm/MultiPackageInstallingSession.java
deleted file mode 100644
index e5ed5d8a5f5b..000000000000
--- a/services/core/java/com/android/server/pm/MultiPackageInstallingSession.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.pm;
-
-import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-
-import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
-import static com.android.server.pm.PackageManagerService.TAG;
-
-import android.annotation.NonNull;
-import android.content.pm.PackageManager;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.util.ArrayMap;
-import android.util.Slog;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Container for a multi-package install which refers to all install sessions and args being
- * committed together.
- */
-final class MultiPackageInstallingSession {
- private final List<InstallingSession> mChildInstallingSessions;
- private final Map<InstallArgs, Integer> mCurrentState;
- @NonNull
- final PackageManagerService mPm;
- final UserHandle mUser;
-
- MultiPackageInstallingSession(UserHandle user, List<InstallingSession> childInstallingSessions,
- PackageManagerService pm)
- throws PackageManagerException {
- if (childInstallingSessions.size() == 0) {
- throw new PackageManagerException("No child sessions found!");
- }
- mPm = pm;
- mUser = user;
- mChildInstallingSessions = childInstallingSessions;
- for (int i = 0; i < childInstallingSessions.size(); i++) {
- final InstallingSession childInstallingSession = childInstallingSessions.get(i);
- childInstallingSession.mParentInstallingSession = this;
- }
- this.mCurrentState = new ArrayMap<>(mChildInstallingSessions.size());
- }
-
- public void start() {
- if (DEBUG_INSTALL) Slog.i(TAG, "start " + mUser + ": " + this);
- Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
- System.identityHashCode(this));
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "start");
- for (InstallingSession childInstallingSession : mChildInstallingSessions) {
- childInstallingSession.handleStartCopy();
- }
- for (InstallingSession childInstallingSession : mChildInstallingSessions) {
- childInstallingSession.handleReturnCode();
- }
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
-
- public void tryProcessInstallRequest(InstallArgs args, int currentStatus) {
- mCurrentState.put(args, currentStatus);
- if (mCurrentState.size() != mChildInstallingSessions.size()) {
- return;
- }
- int completeStatus = PackageManager.INSTALL_SUCCEEDED;
- for (Integer status : mCurrentState.values()) {
- if (status == PackageManager.INSTALL_UNKNOWN) {
- return;
- } else if (status != PackageManager.INSTALL_SUCCEEDED) {
- completeStatus = status;
- break;
- }
- }
- final List<InstallRequest> installRequests = new ArrayList<>(mCurrentState.size());
- for (Map.Entry<InstallArgs, Integer> entry : mCurrentState.entrySet()) {
- installRequests.add(new InstallRequest(entry.getKey(),
- new PackageInstalledInfo(completeStatus)));
- }
- int finalCompleteStatus = completeStatus;
- final InstallPackageHelper installPackageHelper = new InstallPackageHelper(mPm);
- mPm.mHandler.post(() -> installPackageHelper.processInstallRequests(
- finalCompleteStatus == PackageManager.INSTALL_SUCCEEDED /* success */,
- installRequests));
- }
-
- @Override
- public String toString() {
- return "MultiPackageInstallingSession{" + Integer.toHexString(System.identityHashCode(this))
- + "}";
- }
-}
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index c950dcfc30bd..d50e55ee5303 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -62,11 +62,13 @@ import java.io.IOException;
final class PackageHandler extends Handler {
private final PackageManagerService mPm;
private final InstallPackageHelper mInstallPackageHelper;
+ private final RemovePackageHelper mRemovePackageHelper;
PackageHandler(Looper looper, PackageManagerService pm) {
super(looper);
mPm = pm;
mInstallPackageHelper = new InstallPackageHelper(mPm);
+ mRemovePackageHelper = new RemovePackageHelper(mPm);
}
@Override
@@ -107,11 +109,9 @@ final class PackageHandler extends Handler {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1);
} break;
case DEFERRED_NO_KILL_POST_DELETE: {
- synchronized (mPm.mInstallLock) {
- InstallArgs args = (InstallArgs) msg.obj;
- if (args != null) {
- args.doPostDeleteLI(true);
- }
+ InstallArgs args = (InstallArgs) msg.obj;
+ if (args != null) {
+ mRemovePackageHelper.cleanUpResources(args);
}
} break;
case DEFERRED_NO_KILL_INSTALL_OBSERVER:
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index bb23d89d218f..6ee43a0268b6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -379,9 +379,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
// Clean up orphaned staging directories
for (File stage : stagingDirsToRemove) {
Slog.w(TAG, "Deleting orphan stage " + stage);
- synchronized (mPm.mInstallLock) {
- removePackageHelper.removeCodePathLI(stage);
- }
+ removePackageHelper.removeCodePath(stage);
}
}
diff --git a/services/core/java/com/android/server/pm/ReconciledPackage.java b/services/core/java/com/android/server/pm/ReconciledPackage.java
index bd63a1a4f10f..1bfe3576225f 100644
--- a/services/core/java/com/android/server/pm/ReconciledPackage.java
+++ b/services/core/java/com/android/server/pm/ReconciledPackage.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SigningDetails;
@@ -75,7 +76,7 @@ final class ReconciledPackage {
* with the package(s) currently being installed. The to-be installed packages take
* precedence and may shadow already installed packages.
*/
- Map<String, AndroidPackage> getCombinedAvailablePackages() {
+ @NonNull Map<String, AndroidPackage> getCombinedAvailablePackages() {
final ArrayMap<String, AndroidPackage> combined =
new ArrayMap<>(mRequest.mAllPackages.size() + mRequest.mScannedPackages.size());
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 65d3430fe474..f083b67a0402 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -23,6 +23,7 @@ import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
+import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
import static com.android.server.pm.PackageManagerService.RANDOM_DIR_PREFIX;
@@ -30,6 +31,11 @@ import static com.android.server.pm.PackageManagerService.TAG;
import android.annotation.NonNull;
import android.content.pm.PackageManager;
+import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
+import android.os.Environment;
import android.os.Trace;
import android.os.UserHandle;
import android.os.incremental.IncrementalManager;
@@ -78,8 +84,17 @@ final class RemovePackageHelper {
this(pm, new AppDataHelper(pm));
}
+ public void removeCodePath(File codePath) {
+ synchronized (mPm.mInstallLock) {
+ removeCodePathLI(codePath);
+ }
+ }
+
@GuardedBy("mPm.mInstallLock")
- public void removeCodePathLI(File codePath) {
+ private void removeCodePathLI(File codePath) {
+ if (codePath == null || !codePath.exists()) {
+ return;
+ }
if (codePath.isDirectory()) {
final File codePathParent = codePath.getParentFile();
final boolean needRemoveParent = codePathParent.getName().startsWith(RANDOM_DIR_PREFIX);
@@ -118,7 +133,14 @@ final class RemovePackageHelper {
cacher.cleanCachedResult(codePath);
}
- public void removePackageLI(AndroidPackage pkg, boolean chatty) {
+ public void removePackage(AndroidPackage pkg, boolean chatty) {
+ synchronized (mPm.mInstallLock) {
+ removePackageLI(pkg, chatty);
+ }
+ }
+
+ @GuardedBy("mPm.mInstallLock")
+ private void removePackageLI(AndroidPackage pkg, boolean chatty) {
// Remove the parent package setting
PackageStateInternal ps = mPm.snapshotComputer()
.getPackageStateInternal(pkg.getPackageName());
@@ -129,6 +151,7 @@ final class RemovePackageHelper {
}
}
+ @GuardedBy("mPm.mInstallLock")
private void removePackageLI(String packageName, boolean chatty) {
if (DEBUG_INSTALL) {
if (chatty) {
@@ -145,6 +168,7 @@ final class RemovePackageHelper {
}
}
+ @GuardedBy("mPm.mLock")
private void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean chatty) {
mPm.mComponentResolver.removeAllComponents(pkg, chatty);
mPermissionManager.onPackageRemoved(pkg);
@@ -175,7 +199,7 @@ final class RemovePackageHelper {
final int libraryNamesSize = pkg.getLibraryNames().size();
for (i = 0; i < libraryNamesSize; i++) {
String name = pkg.getLibraryNames().get(i);
- if (mSharedLibraries.removeSharedLibraryLPw(name, 0)) {
+ if (mSharedLibraries.removeSharedLibrary(name, 0)) {
if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
@@ -192,7 +216,7 @@ final class RemovePackageHelper {
// Any package can hold SDK or static shared libraries.
if (pkg.getSdkLibName() != null) {
- if (mSharedLibraries.removeSharedLibraryLPw(
+ if (mSharedLibraries.removeSharedLibrary(
pkg.getSdkLibName(), pkg.getSdkLibVersionMajor())) {
if (DEBUG_REMOVE && chatty) {
if (r == null) {
@@ -205,7 +229,7 @@ final class RemovePackageHelper {
}
}
if (pkg.getStaticSharedLibName() != null) {
- if (mSharedLibraries.removeSharedLibraryLPw(pkg.getStaticSharedLibName(),
+ if (mSharedLibraries.removeSharedLibrary(pkg.getStaticSharedLibName(),
pkg.getStaticSharedLibVersion())) {
if (DEBUG_REMOVE && chatty) {
if (r == null) {
@@ -223,12 +247,20 @@ final class RemovePackageHelper {
}
}
+ public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
+ PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
+ synchronized (mPm.mInstallLock) {
+ removePackageDataLIF(deletedPs, allUserHandles, outInfo, flags, writeSettings);
+ }
+ }
+
/*
* This method deletes the package from internal data structures. If the DELETE_KEEP_DATA
* flag is not set, the data directory is removed as well.
* make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application.
*/
+ @GuardedBy("mPm.mInstallLock")
public void removePackageDataLIF(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = deletedPs.getPackageName();
@@ -352,4 +384,74 @@ final class RemovePackageHelper {
});
}
}
+
+ void cleanUpResources(InstallArgs args) {
+ synchronized (mPm.mInstallLock) {
+ cleanUpResourcesLI(args);
+ }
+ }
+
+ // Need installer lock especially for dex file removal.
+ @GuardedBy("mPm.mInstallLock")
+ private void cleanUpResourcesLI(InstallArgs args) {
+ // Try enumerating all code paths before deleting
+ List<String> allCodePaths = Collections.EMPTY_LIST;
+ if (args.mCodeFile != null && args.mCodeFile.exists()) {
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ input.reset(), args.mCodeFile, /* flags */ 0);
+ if (result.isSuccess()) {
+ // Ignore error; we tried our best
+ allCodePaths = result.getResult().getAllApkPaths();
+ }
+ }
+
+ removeCodePathLI(args.mCodeFile);
+ removeDexFilesLI(allCodePaths, args.mInstructionSets);
+ }
+
+ @GuardedBy("mPm.mInstallLock")
+ private void removeDexFilesLI(List<String> allCodePaths, String[] instructionSets) {
+ if (!allCodePaths.isEmpty()) {
+ if (instructionSets == null) {
+ throw new IllegalStateException("instructionSet == null");
+ }
+ String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+ for (String codePath : allCodePaths) {
+ for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+ try {
+ mPm.mInstaller.rmdex(codePath, dexCodeInstructionSet);
+ } catch (Installer.InstallerException ignored) {
+ }
+ }
+ }
+ }
+ }
+
+ void cleanUpForMoveInstall(String volumeUuid, String packageName, String fromCodePath) {
+ final String toPathName = new File(fromCodePath).getName();
+ final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid), toPathName);
+ Slog.d(TAG, "Cleaning up " + packageName + " on " + volumeUuid);
+ final int[] userIds = mPm.mUserManager.getUserIds();
+ synchronized (mPm.mInstallLock) {
+ // Clean up both app data and code
+ // All package moves are frozen until finished
+
+ // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since
+ // this task was only focused on moving data on internal storage.
+ // We don't want ART profiles cleared, because they don't move,
+ // so we would be deleting the only copy (b/149200535).
+ final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
+ for (int userId : userIds) {
+ try {
+ mPm.mInstaller.destroyAppData(volumeUuid, packageName, userId, flags,
+ 0);
+ } catch (Installer.InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
+ }
+ }
+ removeCodePathLI(codeFile);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index fe160e3fee22..0e57c917a72b 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -428,8 +428,7 @@ final class ScanPackageUtils {
pkgSetting.setLastModifiedTime(scanFileTime);
// TODO(b/135203078): Remove, move to constructor
pkgSetting.setPkg(parsedPackage)
- .setFlags(PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting))
- .setPrivateFlags(
+ .setPkgFlags(PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting));
if (parsedPackage.getLongVersionCode() != pkgSetting.getVersionCode()) {
pkgSetting.setLongVersionCode(parsedPackage.getLongVersionCode());
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index b952f80850bb..61a251e19db7 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -146,6 +146,17 @@ public abstract class SettingBase implements Watchable, Snappable {
return this;
}
+ /**
+ * Unconditionally set both mPkgFlags and mPkgPrivateFlags.
+ * Should not be used outside pkgSetting initialization or update.
+ */
+ SettingBase setPkgFlags(int flags, int privateFlags) {
+ this.mPkgFlags = flags;
+ this.mPkgPrivateFlags = privateFlags;
+ onChanged();
+ return this;
+ }
+
public int getFlags() {
return mPkgFlags;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 138915dc42c0..c064324279c1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -987,8 +987,7 @@ public final class Settings implements Watchable, Snappable {
// Update new package state.
.setLastModifiedTime(codePath.lastModified())
.setDomainSetId(domainSetId);
- pkgSetting.setFlags(pkgFlags)
- .setPrivateFlags(pkgPrivateFlags);
+ pkgSetting.setPkgFlags(pkgFlags, pkgPrivateFlags);
} else {
pkgSetting = new PackageSetting(pkgName, realPkgName, codePath,
legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
@@ -1175,15 +1174,15 @@ public final class Settings implements Watchable, Snappable {
.setUsesStaticLibrariesVersions(null);
}
- // These two flags are preserved from the existing PackageSetting. Copied from prior code,
- // unclear if this is actually necessary.
- boolean wasExternalStorage = (pkgSetting.getFlags()
- & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
- if (wasExternalStorage) {
- pkgFlags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
- } else {
- pkgFlags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
- }
+ // If what we are scanning is a system (and possibly privileged) package,
+ // then make it so, regardless of whether it was previously installed only
+ // in the data partition. Reset first.
+ int newPkgFlags = pkgSetting.getFlags();
+ newPkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
+ newPkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
+ // Only set pkgFlags.
+ pkgSetting.setPkgFlags(newPkgFlags, pkgSetting.getPrivateFlags());
+
boolean wasRequiredForSystemUser = (pkgSetting.getPrivateFlags()
& ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER) != 0;
if (wasRequiredForSystemUser) {
@@ -1191,9 +1190,7 @@ public final class Settings implements Watchable, Snappable {
} else {
pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER;
}
-
- pkgSetting.setFlags(pkgFlags)
- .setPrivateFlags(pkgPrivateFlags);
+ pkgSetting.setPrivateFlags(pkgPrivateFlags);
}
/**
diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
index 479a404c88bf..7432b8446f35 100644
--- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
+++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
import static com.android.server.pm.PackageManagerService.TAG;
import android.annotation.NonNull;
@@ -258,11 +259,13 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
* Given the library name, returns a list of shared libraries on all versions.
* TODO: Remove, this is used for live mutation outside of the defined commit path
*/
- @GuardedBy("mPm.mLock")
+
@Override
public @NonNull WatchedLongSparseArray<SharedLibraryInfo> getSharedLibraryInfos(
@NonNull String libName) {
- return mSharedLibraries.get(libName);
+ synchronized (mPm.mLock) {
+ return mSharedLibraries.get(libName);
+ }
}
@VisibleForTesting
@@ -381,6 +384,11 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
return false;
}
+ @Nullable SharedLibraryInfo getLatestStaticSharedLibraVersion(@NonNull AndroidPackage pkg) {
+ synchronized (mPm.mLock) {
+ return getLatestStaticSharedLibraVersionLPr(pkg);
+ }
+ }
/**
* Given a package of static shared library, returns its shared library info of
* the latest version.
@@ -389,7 +397,8 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
* @return The latest version of shared library info.
*/
@GuardedBy("mPm.mLock")
- @Nullable SharedLibraryInfo getLatestStaticSharedLibraVersionLPr(@NonNull AndroidPackage pkg) {
+ @Nullable
+ private SharedLibraryInfo getLatestStaticSharedLibraVersionLPr(@NonNull AndroidPackage pkg) {
WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
pkg.getStaticSharedLibName());
if (versionedLib == null) {
@@ -524,15 +533,26 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
* @param changingLibSetting The updating library package setting.
* @param availablePackages All installed packages and current being installed packages.
*/
- @GuardedBy("mPm.mLock")
- void updateSharedLibrariesLPw(@NonNull AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
+ void updateSharedLibraries(@NonNull AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
@Nullable AndroidPackage changingLib, @Nullable PackageSetting changingLibSetting,
@NonNull Map<String, AndroidPackage> availablePackages)
throws PackageManagerException {
final ArrayList<SharedLibraryInfo> sharedLibraryInfos = collectSharedLibraryInfos(
pkg, availablePackages, null /* newLibraries */);
- executeSharedLibrariesUpdateLPw(pkg, pkgSetting, changingLib, changingLibSetting,
- sharedLibraryInfos, mPm.mUserManager.getUserIds());
+ synchronized (mPm.mLock) {
+ executeSharedLibrariesUpdateLPw(pkg, pkgSetting, changingLib, changingLibSetting,
+ sharedLibraryInfos, mPm.mUserManager.getUserIds());
+ }
+ }
+
+ void executeSharedLibrariesUpdate(AndroidPackage pkg,
+ @NonNull PackageSetting pkgSetting, @Nullable AndroidPackage changingLib,
+ @Nullable PackageSetting changingLibSetting,
+ ArrayList<SharedLibraryInfo> usesLibraryInfos, int[] allUsers) {
+ synchronized (mPm.mLock) {
+ executeSharedLibrariesUpdateLPw(pkg, pkgSetting, changingLib, changingLibSetting,
+ usesLibraryInfos, allUsers);
+ }
}
/**
@@ -547,7 +567,7 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
* @param allUsers All user ids on the device.
*/
@GuardedBy("mPm.mLock")
- void executeSharedLibrariesUpdateLPw(AndroidPackage pkg,
+ private void executeSharedLibrariesUpdateLPw(AndroidPackage pkg,
@NonNull PackageSetting pkgSetting, @Nullable AndroidPackage changingLib,
@Nullable PackageSetting changingLibSetting,
ArrayList<SharedLibraryInfo> usesLibraryInfos, int[] allUsers) {
@@ -610,6 +630,31 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
return false;
}
+ ArrayList<AndroidPackage> commitSharedLibraryChanges(@NonNull AndroidPackage pkg,
+ @NonNull PackageSetting pkgSetting, List<SharedLibraryInfo> allowedSharedLibraryInfos,
+ @NonNull Map<String, AndroidPackage> combinedSigningDetails, int scanFlags) {
+ if (ArrayUtils.isEmpty(allowedSharedLibraryInfos)) {
+ return null;
+ }
+ synchronized (mPm.mLock) {
+ for (SharedLibraryInfo info : allowedSharedLibraryInfos) {
+ commitSharedLibraryInfoLPw(info);
+ }
+ try {
+ // Shared libraries for the package need to be updated.
+ updateSharedLibraries(pkg, pkgSetting, null, null, combinedSigningDetails);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateSharedLibraries failed: ", e);
+ }
+ // Update all applications that use this library. Skip when booting
+ // since this will be done after all packages are scaned.
+ if ((scanFlags & SCAN_BOOTING) == 0) {
+ return updateAllSharedLibrariesLPw(pkg, pkgSetting, combinedSigningDetails);
+ }
+ }
+ return null;
+ }
+
/**
* Update shared library dependencies and code paths for applications that are using the
* library {@code updatedPkg}. Update all applications if the {@code updatedPkg} is null.
@@ -666,7 +711,7 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
}
}
try {
- updateSharedLibrariesLPw(pkg, pkgSetting, changingPkg,
+ updateSharedLibraries(pkg, pkgSetting, changingPkg,
changingPkgSetting, availablePackages);
} catch (PackageManagerException e) {
// If a system app update or an app and a required lib missing we
@@ -677,9 +722,11 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
if (!pkg.isSystem() || pkgSetting.getPkgState().isUpdatedSystemApp()) {
final int flags = pkgSetting.getPkgState().isUpdatedSystemApp()
? PackageManager.DELETE_KEEP_DATA : 0;
- mDeletePackageHelper.deletePackageLIF(pkg.getPackageName(), null, true,
- mPm.mUserManager.getUserIds(), flags, null,
- true);
+ synchronized (mPm.mInstallLock) {
+ mDeletePackageHelper.deletePackageLIF(pkg.getPackageName(), null, true,
+ mPm.mUserManager.getUserIds(), flags, null,
+ true);
+ }
}
Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
}
@@ -711,6 +758,7 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
* Add a shared library info to the system. This is invoked when the package is being added or
* scanned.
*/
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@GuardedBy("mPm.mLock")
void commitSharedLibraryInfoLPw(@NonNull SharedLibraryInfo libraryInfo) {
final String name = libraryInfo.getName();
@@ -729,45 +777,46 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
/**
* Remove a shared library from the system.
*/
- @GuardedBy("mPm.mLock")
- boolean removeSharedLibraryLPw(@NonNull String libName, long version) {
- WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
- if (versionedLib == null) {
- return false;
- }
- final int libIdx = versionedLib.indexOfKey(version);
- if (libIdx < 0) {
- return false;
- }
- SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx);
+ boolean removeSharedLibrary(@NonNull String libName, long version) {
+ synchronized (mPm.mLock) {
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
+ if (versionedLib == null) {
+ return false;
+ }
+ final int libIdx = versionedLib.indexOfKey(version);
+ if (libIdx < 0) {
+ return false;
+ }
+ SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx);
- final Computer snapshot = mPm.snapshotComputer();
+ final Computer snapshot = mPm.snapshotComputer();
- // Remove the shared library overlays from its dependent packages.
- for (int currentUserId : mPm.mUserManager.getUserIds()) {
- final List<VersionedPackage> dependents = snapshot.getPackagesUsingSharedLibrary(
- libraryInfo, 0, Process.SYSTEM_UID, currentUserId);
- if (dependents == null) {
- continue;
- }
- for (VersionedPackage dependentPackage : dependents) {
- final PackageSetting ps = mPm.mSettings.getPackageLPr(
- dependentPackage.getPackageName());
- if (ps != null) {
- ps.setOverlayPathsForLibrary(libraryInfo.getName(), null, currentUserId);
+ // Remove the shared library overlays from its dependent packages.
+ for (int currentUserId : mPm.mUserManager.getUserIds()) {
+ final List<VersionedPackage> dependents = snapshot.getPackagesUsingSharedLibrary(
+ libraryInfo, 0, Process.SYSTEM_UID, currentUserId);
+ if (dependents == null) {
+ continue;
+ }
+ for (VersionedPackage dependentPackage : dependents) {
+ final PackageSetting ps = mPm.mSettings.getPackageLPr(
+ dependentPackage.getPackageName());
+ if (ps != null) {
+ ps.setOverlayPathsForLibrary(libraryInfo.getName(), null, currentUserId);
+ }
}
}
- }
- versionedLib.remove(version);
- if (versionedLib.size() <= 0) {
- mSharedLibraries.remove(libName);
- if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
- mStaticLibsByDeclaringPackage.remove(libraryInfo.getDeclaringPackage()
- .getPackageName());
+ versionedLib.remove(version);
+ if (versionedLib.size() <= 0) {
+ mSharedLibraries.remove(libName);
+ if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
+ mStaticLibsByDeclaringPackage.remove(libraryInfo.getDeclaringPackage()
+ .getPackageName());
+ }
}
+ return true;
}
- return true;
}
/**
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index fe1c83bab30c..f621d8b2533a 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -346,9 +346,7 @@ public final class StorageEventHelper extends StorageEventListener {
for (int i = 0; i < fileToDeleteCount; i++) {
File fileToDelete = filesToDelete.get(i);
logCriticalInfo(Log.WARN, "Destroying orphaned at " + fileToDelete);
- synchronized (mPm.mInstallLock) {
- mRemovePackageHelper.removeCodePathLI(fileToDelete);
- }
+ mRemovePackageHelper.removeCodePath(fileToDelete);
}
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 598ea8c259c3..988b4eba852e 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1226,8 +1226,8 @@ public final class PowerManagerService extends SystemService
millisUntilNormalTimeout =
powerGroup.getLastUserActivityTimeLocked() + screenOffTimeout - currentTime;
userActivityInternal(Display.DEFAULT_DISPLAY, currentTime,
- PowerManager.USER_ACTIVITY_EVENT_FACE_DOWN, /* flags= */0,
- Process.SYSTEM_UID);
+ PowerManager.USER_ACTIVITY_EVENT_FACE_DOWN,
+ PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS, Process.SYSTEM_UID);
}
}
if (isFaceDown) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
index b42a3b0719df..e59a404ebed4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
@@ -39,6 +39,10 @@ import com.android.server.testutils.spy
import com.android.server.testutils.whenever
import com.android.server.utils.WatchedLongSparseArray
import com.google.common.truth.Truth.assertThat
+import java.io.File
+import kotlin.test.assertFailsWith
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
import libcore.util.HexEncoding
import org.junit.Before
import org.junit.Rule
@@ -51,10 +55,6 @@ import org.mockito.Mock
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import java.io.File
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
@RunWith(JUnit4::class)
class SharedLibrariesImplTest {
@@ -186,7 +186,7 @@ class SharedLibrariesImplTest {
val staticInfo = mSharedLibrariesImpl
.getSharedLibraryInfo(STATIC_LIB_NAME, STATIC_LIB_VERSION)!!
- mSharedLibrariesImpl.removeSharedLibraryLPw(STATIC_LIB_NAME, STATIC_LIB_VERSION)
+ mSharedLibrariesImpl.removeSharedLibrary(STATIC_LIB_NAME, STATIC_LIB_VERSION)
assertThat(mSharedLibrariesImpl.getSharedLibraryInfos(STATIC_LIB_NAME)).isNull()
assertThat(mSharedLibrariesImpl
@@ -208,7 +208,7 @@ class SharedLibrariesImplTest {
staticLibrary = STATIC_LIB_NAME, staticLibraryVersion = 10L)
val latestInfo =
- mSharedLibrariesImpl.getLatestStaticSharedLibraVersionLPr(pair.second)!!
+ mSharedLibrariesImpl.getLatestStaticSharedLibraVersion(pair.second)!!
assertThat(latestInfo).isNotNull()
assertThat(latestInfo.name).isEqualTo(STATIC_LIB_NAME)
@@ -237,7 +237,7 @@ class SharedLibrariesImplTest {
testPackageSetting.setPkgStateLibraryFiles(listOf())
assertThat(testPackageSetting.usesLibraryFiles).isEmpty()
- mSharedLibrariesImpl.updateSharedLibrariesLPw(testPackageSetting.pkg, testPackageSetting,
+ mSharedLibrariesImpl.updateSharedLibraries(testPackageSetting.pkg, testPackageSetting,
null /* changingLib */, null /* changingLibSetting */, mExistingPackages)
assertThat(testPackageSetting.usesLibraryFiles).hasSize(1)
@@ -250,7 +250,7 @@ class SharedLibrariesImplTest {
testPackageSetting.setPkgStateLibraryFiles(listOf())
assertThat(testPackageSetting.usesLibraryFiles).isEmpty()
- mSharedLibrariesImpl.updateSharedLibrariesLPw(testPackageSetting.pkg, testPackageSetting,
+ mSharedLibrariesImpl.updateSharedLibraries(testPackageSetting.pkg, testPackageSetting,
null /* changingLib */, null /* changingLibSetting */, mExistingPackages)
assertThat(testPackageSetting.usesLibraryFiles).hasSize(2)
@@ -264,7 +264,7 @@ class SharedLibrariesImplTest {
testPackageSetting.setPkgStateLibraryFiles(listOf())
assertThat(testPackageSetting.usesLibraryFiles).isEmpty()
- mSharedLibrariesImpl.updateSharedLibrariesLPw(testPackageSetting.pkg, testPackageSetting,
+ mSharedLibrariesImpl.updateSharedLibraries(testPackageSetting.pkg, testPackageSetting,
null /* changingLib */, null /* changingLibSetting */, mExistingPackages)
assertThat(testPackageSetting.usesLibraryFiles).hasSize(3)
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index ece0a627f051..b0738fdb78d0 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -17,7 +17,11 @@
package com.android.server.display;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PropertyInvalidatedCache;
@@ -45,18 +49,21 @@ public class LogicalDisplayTest {
private LogicalDisplay mLogicalDisplay;
private DisplayDevice mDisplayDevice;
+ private final DisplayDeviceInfo mDisplayDeviceInfo = new DisplayDeviceInfo();
@Before
public void setUp() {
// Share classloader to allow package private access.
System.setProperty("dexmaker.share_classloader", "true");
mDisplayDevice = mock(DisplayDevice.class);
- DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
- displayDeviceInfo.width = DISPLAY_WIDTH;
- displayDeviceInfo.height = DISPLAY_HEIGHT;
- displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
mLogicalDisplay = new LogicalDisplay(DISPLAY_ID, LAYER_STACK, mDisplayDevice);
- when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(displayDeviceInfo);
+
+ mDisplayDeviceInfo.copyFrom(new DisplayDeviceInfo());
+ mDisplayDeviceInfo.width = DISPLAY_WIDTH;
+ mDisplayDeviceInfo.height = DISPLAY_HEIGHT;
+ mDisplayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
+ mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
+ when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(mDisplayDeviceInfo);
// Disable binder caches in this process.
PropertyInvalidatedCache.disableForTestMode();
@@ -103,4 +110,33 @@ public class LogicalDisplayTest {
mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition());
}
+
+ @Test
+ public void testDisplayInputFlags() {
+ SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+ verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT));
+ reset(t);
+
+ mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+ mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+ verify(t).setDisplayFlags(any(), eq(0));
+ reset(t);
+
+ mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL;
+ mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+ verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT));
+ reset(t);
+
+ mLogicalDisplay.setPhase(LogicalDisplay.DISPLAY_PHASE_DISABLED);
+ mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+ verify(t).setDisplayFlags(any(), eq(0));
+ reset(t);
+
+ mLogicalDisplay.setPhase(LogicalDisplay.DISPLAY_PHASE_ENABLED);
+ mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
+ mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+ verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT));
+ reset(t);
+ }
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index ddb88cb01b0b..86b8e5fa1647 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -86,55 +86,6 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Test
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
/**
* Checks that the [ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME] activity is visible at
* the start of the transition, that
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index f8cdfb3f618d..34c0b2396d01 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -110,16 +110,6 @@ open class OpenAppFromOverviewTest(
/** {@inheritDoc} */
@Presubmit
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
override fun appLayerBecomesVisible() = super.appLayerBecomesVisible_warmStart()
/** {@inheritDoc} */
@@ -127,17 +117,6 @@ open class OpenAppFromOverviewTest(
@Test
override fun appWindowBecomesVisible() = super.appWindowBecomesVisible_warmStart()
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appWindowReplacesLauncherAsTopWindow() =
- super.appWindowReplacesLauncherAsTopWindow()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
-
companion object {
/**
* Creates the test configurations.