Merge "Send cached target duration when creating sessions" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 09f50a8..08a09e1 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -15,6 +15,7 @@
aconfig_srcjars = [
":android.app.usage.flags-aconfig-java{.generated_srcjars}",
":android.content.pm.flags-aconfig-java{.generated_srcjars}",
+ ":android.hardware.radio.flags-aconfig-java{.generated_srcjars}",
":android.nfc.flags-aconfig-java{.generated_srcjars}",
":android.os.flags-aconfig-java{.generated_srcjars}",
":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
@@ -341,3 +342,16 @@
aconfig_declarations: "android.app.flags-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+
+// Broadcast Radio
+aconfig_declarations {
+ name: "android.hardware.radio.flags-aconfig",
+ package: "android.hardware.radio",
+ srcs: ["core/java/android/hardware/radio/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.hardware.radio.flags-aconfig-java",
+ aconfig_declarations: "android.hardware.radio.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index ed0f872..15bd1dc 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -22,8 +22,10 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.FillRequest;
+import android.text.InputType;
import android.text.Spanned;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.view.View;
@@ -2452,7 +2454,7 @@
+ node.getTextStyle());
Log.i(TAG, prefix + " Text color fg: #" + Integer.toHexString(node.getTextColor())
+ ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
- Log.i(TAG, prefix + " Input type: " + node.getInputType());
+ Log.i(TAG, prefix + " Input type: " + getInputTypeString(node.getInputType()));
Log.i(TAG, prefix + " Resource id: " + node.getTextIdEntry());
}
String webDomain = node.getWebDomain();
@@ -2664,4 +2666,33 @@
return new AssistStructure[size];
}
};
+
+ private static final ArrayMap<Integer, String> INPUT_TYPE_VARIATIONS = new ArrayMap<>();
+ static {
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS, "EmailSubject");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS, "PostalAddress");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_PERSON_NAME, "PersonName");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_PASSWORD, "Password");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD, "VisiblePassword");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_URI, "URI");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS, "WebEmailAddress");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD, "WebPassword");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE, "LongMessage");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE, "ShortMessage");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_FLAG_MULTI_LINE, "MultiLine");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE, "ImeMultiLine");
+ INPUT_TYPE_VARIATIONS.put(InputType.TYPE_TEXT_VARIATION_FILTER, "Filter");
+ }
+
+ private static String getInputTypeString(int inputType) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(inputType);
+ sb.append("(class=").append(inputType & InputType.TYPE_MASK_CLASS).append(')');
+ for (int variation : INPUT_TYPE_VARIATIONS.keySet()) {
+ if ((variation & inputType) == variation) {
+ sb.append('|').append(INPUT_TYPE_VARIATIONS.get(variation));
+ }
+ }
+ return sb.toString();
+ }
}
diff --git a/core/java/android/hardware/radio/flags.aconfig b/core/java/android/hardware/radio/flags.aconfig
new file mode 100644
index 0000000..dbc1a4b
--- /dev/null
+++ b/core/java/android/hardware/radio/flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.hardware.radio"
+
+flag {
+ name: "hd_radio_improved"
+ namespace: "car_framework"
+ description: "Feature flag for improved HD radio support with less vendor extensions"
+ bug: "280300929"
+}
diff --git a/core/java/android/net/network-policy-restrictions.md b/core/java/android/net/network-policy-restrictions.md
index 04c658c..20f3d74 100644
--- a/core/java/android/net/network-policy-restrictions.md
+++ b/core/java/android/net/network-policy-restrictions.md
@@ -29,8 +29,8 @@
| **DS** | *AL* | ok | blk | ok | ok |
| **ON** | *!AL* | blk | blk | blk | blk |
| | *DL* | blk | blk | blk | blk |
-| **DS** | *AL* | blk | blk | ok | ok |
-| **OFF** | *!AL* | blk | blk | ok | ok |
+| **DS** | *AL* | ok | blk | ok | ok |
+| **OFF** | *!AL* | ok | blk | ok | ok |
| | *DL* | blk | blk | blk | blk |
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
index 2dbb5da..dae3202 100644
--- a/core/java/android/security/FileIntegrityManager.java
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -76,28 +76,38 @@
* Enables fs-verity to the owned file under the calling app's private directory. It always uses
* the common configuration, i.e. SHA-256 digest algorithm, 4K block size, and without salt.
*
- * The operation can only succeed when the file is not opened as writable by any process.
+ * <p>For enabling fs-verity to succeed, the device must support fs-verity, the file must be
+ * writable by the app and not already have fs-verity enabled, and the file must not currently
+ * be open for writing by any process. To check whether the device supports fs-verity, use
+ * {@link #isApkVeritySupported()}.
*
- * It takes O(file size) time to build the underlying data structure for continuous
+ * <p>It takes O(file size) time to build the underlying data structure for continuous
* verification. The operation is atomic, i.e. it's either enabled or not, even in case of
* power failure during or after the call.
*
- * Note for the API users: When the file's authenticity is crucial, the app typical needs to
+ * <p>Note for the API users: When the file's authenticity is crucial, the app typical needs to
* perform a signature check by itself before using the file. The signature is often delivered
* as a separate file and stored next to the targeting file in the filesystem. The public key of
* the signer (normally the same app developer) can be put in the APK, and the app can use the
* public key to verify the signature to the file's actual fs-verity digest (from {@link
- * #getFsVerityDigest}) before using the file. The exact format is not prescribed by the
+ * #getFsVerityDigest(File)}) before using the file. The exact format is not prescribed by the
* framework. App developers may choose to use common practices like JCA for the signing and
* verification, or their own preferred approach.
*
- * @param file The file to enable fs-verity. It should be an absolute path.
+ * @param file The file to enable fs-verity. It must represent an absolute path.
+ * @throws IllegalArgumentException If the provided file is not an absolute path.
+ * @throws IOException If the operation failed.
*
* @see <a href="https://www.kernel.org/doc/html/next/filesystems/fsverity.html">Kernel doc</a>
*/
@FlaggedApi(Flags.FLAG_FSVERITY_API)
public void setupFsVerity(@NonNull File file) throws IOException {
if (!file.isAbsolute()) {
+ // fs-verity is to be enabled by installd, which enforces the validation to the
+ // (untrusted) file path passed from here. To make this less error prone, installd
+ // accepts only absolute path. When a relative path is provided, we fail with an
+ // explicit exception to help developers understand the requirement to use an absolute
+ // path.
throw new IllegalArgumentException("Expect an absolute path");
}
IFsveritySetupAuthToken authToken;
@@ -121,11 +131,12 @@
}
/**
- * Returns the fs-verity digest for the owned file under the calling app's
- * private directory, or null when the file does not have fs-verity enabled.
+ * Returns the fs-verity digest for the owned file under the calling app's private directory, or
+ * null when the file does not have fs-verity enabled (including when fs-verity is not supported
+ * on older devices).
*
* @param file The file to measure the fs-verity digest.
- * @return The fs-verity digeset in byte[], null if none.
+ * @return The fs-verity digest in byte[], null if none.
* @see <a href="https://www.kernel.org/doc/html/next/filesystems/fsverity.html">Kernel doc</a>
*/
@FlaggedApi(Flags.FLAG_FSVERITY_API)
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0ba5d06..f421351 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3858,9 +3858,7 @@
mPendingTransitions.clear();
}
- if (mActiveSurfaceSyncGroup != null) {
- mActiveSurfaceSyncGroup.markSyncReady();
- }
+ handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mPendingTransaction);
} else if (cancelAndRedraw) {
mLastPerformTraversalsSkipDrawReason = cancelDueToPreDrawListener
? "predraw_" + mAttachInfo.mTreeObserver.getLastDispatchOnPreDrawCanceledReason()
@@ -3874,8 +3872,8 @@
}
mPendingTransitions.clear();
}
- if (!performDraw(mActiveSurfaceSyncGroup) && mActiveSurfaceSyncGroup != null) {
- mActiveSurfaceSyncGroup.markSyncReady();
+ if (!performDraw(mActiveSurfaceSyncGroup)) {
+ handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mPendingTransaction);
}
}
@@ -3890,6 +3888,7 @@
mReportNextDraw = false;
mLastReportNextDrawReason = null;
mActiveSurfaceSyncGroup = null;
+ mHasPendingTransactions = false;
mSyncBuffer = false;
if (isInWMSRequestedSync()) {
mWmsRequestSyncGroup.markSyncReady();
@@ -4688,7 +4687,8 @@
return false;
}
- final boolean fullRedrawNeeded = mFullRedrawNeeded || surfaceSyncGroup != null;
+ final boolean fullRedrawNeeded =
+ mFullRedrawNeeded || surfaceSyncGroup != null || mHasPendingTransactions;
mFullRedrawNeeded = false;
mIsDrawing = true;
@@ -4718,8 +4718,15 @@
mAttachInfo.mPendingAnimatingRenderNodes.clear();
}
- if (mReportNextDraw) {
+ final Transaction pendingTransaction;
+ if (!usingAsyncReport && mHasPendingTransactions) {
+ pendingTransaction = new Transaction();
+ pendingTransaction.merge(mPendingTransaction);
+ } else {
+ pendingTransaction = null;
+ }
+ if (mReportNextDraw) {
// if we're using multi-thread renderer, wait for the window frame draws
if (mWindowDrawCountDown != null) {
try {
@@ -4741,9 +4748,7 @@
if (mSurfaceHolder != null && mSurface.isValid()) {
usingAsyncReport = true;
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() -> {
- if (surfaceSyncGroup != null) {
- surfaceSyncGroup.markSyncReady();
- }
+ handleSyncRequestWhenNoAsyncDraw(surfaceSyncGroup, pendingTransaction);
});
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
@@ -4756,15 +4761,27 @@
}
}
- if (surfaceSyncGroup != null && !usingAsyncReport) {
- surfaceSyncGroup.markSyncReady();
+ if (!usingAsyncReport) {
+ handleSyncRequestWhenNoAsyncDraw(surfaceSyncGroup, pendingTransaction);
}
+
if (mPerformContentCapture) {
performContentCaptureInitialReport();
}
return true;
}
+ private void handleSyncRequestWhenNoAsyncDraw(SurfaceSyncGroup surfaceSyncGroup,
+ @Nullable Transaction pendingTransaction) {
+ if (surfaceSyncGroup != null) {
+ if (pendingTransaction != null) {
+ surfaceSyncGroup.addTransaction(pendingTransaction);
+ }
+ surfaceSyncGroup.markSyncReady();
+ } else if (pendingTransaction != null) {
+ pendingTransaction.apply();
+ }
+ }
/**
* Checks (and caches) if content capture is enabled for this context.
*/
@@ -4850,8 +4867,8 @@
}
}
- private boolean draw(boolean fullRedrawNeeded,
- @Nullable SurfaceSyncGroup activeSyncGroup, boolean syncBuffer) {
+ private boolean draw(boolean fullRedrawNeeded, @Nullable SurfaceSyncGroup activeSyncGroup,
+ boolean syncBuffer) {
Surface surface = mSurface;
if (!surface.isValid()) {
return false;
@@ -4995,12 +5012,11 @@
mAttachInfo.mThreadedRenderer.forceDrawNextFrame();
}
} else if (mHasPendingTransactions) {
- // Register a calback if there's no sync involved but there were calls to
+ // Register a callback if there's no sync involved but there were calls to
// applyTransactionOnDraw. If there is a sync involved, the sync callback will
// handle merging the pending transaction.
registerCallbackForPendingTransactions();
}
- mHasPendingTransactions = false;
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
} else {
@@ -8977,13 +8993,7 @@
mAdded = false;
AnimationHandler.removeRequestor(this);
}
- if (mActiveSurfaceSyncGroup != null) {
- mActiveSurfaceSyncGroup.markSyncReady();
- mActiveSurfaceSyncGroup = null;
- }
- if (mHasPendingTransactions) {
- mPendingTransaction.apply();
- }
+ handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mPendingTransaction);
WindowManagerGlobal.getInstance().doRemoveView(this);
}
@@ -11502,9 +11512,7 @@
Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer);
}
- Transaction t = new Transaction();
- t.merge(mPendingTransaction);
-
+ surfaceSyncGroup.addTransaction(mPendingTransaction);
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public void onFrameDraw(long frame) {
@@ -11518,7 +11526,6 @@
+ frame + ".");
}
- mergeWithNextTransaction(t, frame);
// If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
// SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
// any blast sync or commit callback, and the code should directly call
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java
index 9b10a7f..932608a3 100644
--- a/core/java/android/window/TransitionRequestInfo.java
+++ b/core/java/android/window/TransitionRequestInfo.java
@@ -16,6 +16,8 @@
package android.window;
+import static android.view.WindowManager.transitTypeToString;
+
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
@@ -88,6 +90,11 @@
this(type, triggerTask, null /* pipTask */, remoteTransition, displayChange, flags);
}
+ /** @hide */
+ String typeToString() {
+ return transitTypeToString(mType);
+ }
+
/** Requested change to a display. */
@DataClass(genToString = true, genSetters = true, genBuilder = false, genConstructor = false)
public static class DisplayChange implements Parcelable {
@@ -263,7 +270,7 @@
};
@DataClass.Generated(
- time = 1693425051905L,
+ time = 1695667226050L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nprivate boolean mPhysicalDisplayChanged\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)")
@@ -298,11 +305,11 @@
* @param type
* The type of the transition being requested.
* @param triggerTask
- * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * If non-null, the task containing the activity whose lifecycle change (start or
* finish) has caused this transition to occur.
* @param pipTask
- * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
- * finish) has caused this transition to occur.
+ * If non-null, the task containing the pip activity that participates in this
+ * transition.
* @param remoteTransition
* If non-null, a remote-transition associated with the source of this transition.
* @param displayChange
@@ -431,7 +438,7 @@
// String fieldNameToString() { ... }
return "TransitionRequestInfo { " +
- "type = " + mType + ", " +
+ "type = " + typeToString() + ", " +
"triggerTask = " + mTriggerTask + ", " +
"pipTask = " + mPipTask + ", " +
"remoteTransition = " + mRemoteTransition + ", " +
@@ -506,10 +513,10 @@
};
@DataClass.Generated(
- time = 1693425051928L,
+ time = 1695667226088L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
- inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mPipTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.window.TransitionRequestInfo.DisplayChange mDisplayChange\nprivate final int mFlags\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
+ inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mPipTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.window.TransitionRequestInfo.DisplayChange mDisplayChange\nprivate final int mFlags\n java.lang.String typeToString()\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 0d1871d..663067c 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -203,14 +203,22 @@
}
return false;
}
-
+
+ /**
+ * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED
+ * Intent.ACTION_PACKAGE_CHANGED} being received, this callback
+ * has extras passed in.
+ */
+ public void onPackageChangedWithExtras(String packageName, Bundle extras) {
+ }
+
public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
return false;
}
public void onHandleUserStop(Intent intent, int userHandle) {
}
-
+
public void onUidRemoved(int uid) {
}
@@ -238,21 +246,34 @@
}
/**
+ * Called when a package disappears with extras passed in.
+ */
+ public void onPackageDisappearedWithExtras(String packageName, Bundle extras) {
+ }
+
+ /**
* Called when a package appears for any reason.
*/
public void onPackageAppeared(String packageName, int reason) {
}
+
+ /**
+ * Called when a package appears with extras passed in.
+ */
+ public void onPackageAppearedWithExtras(String packageName, Bundle extras) {
+ }
+
/**
* Called when an existing package is updated or its disabled state changes.
*/
public void onPackageModified(@NonNull String packageName) {
}
-
+
public boolean didSomePackagesChange() {
return mSomePackagesChanged;
}
-
+
public int isPackageAppearing(String packageName) {
if (mAppearingPackages != null) {
for (int i=mAppearingPackages.length-1; i>=0; i--) {
@@ -381,6 +402,7 @@
mChangeType = PACKAGE_PERMANENT_CHANGE;
onPackageAdded(pkg, uid);
}
+ onPackageAppearedWithExtras(pkg, intent.getExtras());
onPackageAppeared(pkg, mChangeType);
}
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
@@ -403,6 +425,7 @@
onPackageRemovedAllUsers(pkg, uid);
}
}
+ onPackageDisappearedWithExtras(pkg, intent.getExtras());
onPackageDisappeared(pkg, mChangeType);
}
} else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
@@ -417,6 +440,7 @@
if (onPackageChanged(pkg, uid, mModifiedComponents)) {
mSomePackagesChanged = true;
}
+ onPackageChangedWithExtras(pkg, intent.getExtras());
onPackageModified(pkg);
}
} else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
diff --git a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
index e082c25..c7eddabe 100644
--- a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
+++ b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
@@ -17,7 +17,6 @@
package com.android.internal.content;
import static com.google.common.truth.Truth.assertThat;
-
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -28,6 +27,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
@@ -36,6 +36,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -45,6 +46,7 @@
@RunWith(AndroidJUnit4.class)
public class PackageMonitorTest {
private static final String FAKE_PACKAGE_NAME = "com.android.internal.content.fakeapp";
+ private static final String FAKE_EXTRA_REASON = "android.intent.extra.fakereason";
private static final int FAKE_PACKAGE_UID = 123;
private static final int FAKE_USER_ID = 0;
private static final int WAIT_CALLBACK_CALLED_IN_MS = 300;
@@ -245,6 +247,7 @@
intent.setData(Uri.fromParts("package", FAKE_PACKAGE_NAME, null));
intent.putExtra(Intent.EXTRA_USER_HANDLE, FAKE_USER_ID);
intent.putExtra(Intent.EXTRA_UID, FAKE_PACKAGE_UID);
+ intent.putExtra(Intent.EXTRA_REASON, FAKE_EXTRA_REASON);
String [] packageList = new String[]{FAKE_PACKAGE_NAME};
intent.putExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, packageList);
spyPackageMonitor.doHandlePackageEvent(intent);
@@ -253,6 +256,20 @@
verify(spyPackageMonitor, times(1))
.onPackageChanged(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID), eq(packageList));
verify(spyPackageMonitor, times(1)).onPackageModified(eq(FAKE_PACKAGE_NAME));
+
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1)).onPackageChangedWithExtras(eq(FAKE_PACKAGE_NAME),
+ argumentCaptor.capture());
+
+ Bundle capturedExtras = argumentCaptor.getValue();
+ Bundle expectedExtras = intent.getExtras();
+ assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_UID))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REASON))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REASON));
+
verify(spyPackageMonitor, times(1)).onSomePackagesChanged();
verify(spyPackageMonitor, times(1)).onFinishPackageChanges();
}
@@ -272,6 +289,21 @@
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
verify(spyPackageMonitor, times(1))
.onPackageUpdateStarted(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
+
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1)).onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME),
+ argumentCaptor.capture());
+ Bundle capturedExtras = argumentCaptor.getValue();
+ Bundle expectedExtras = intent.getExtras();
+ assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_UID))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REPLACING))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REPLACING));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS));
+
verify(spyPackageMonitor, times(1))
.onPackageDisappeared(eq(FAKE_PACKAGE_NAME), eq(PackageMonitor.PACKAGE_UPDATING));
verify(spyPackageMonitor, times(1)).onFinishPackageChanges();
@@ -295,6 +327,21 @@
.onPackageRemoved(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
verify(spyPackageMonitor, times(1))
.onPackageRemovedAllUsers(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
+
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1)).onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME),
+ argumentCaptor.capture());
+ Bundle capturedExtras = argumentCaptor.getValue();
+ Bundle expectedExtras = intent.getExtras();
+ assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_UID))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REPLACING))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REPLACING));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS));
+
verify(spyPackageMonitor, times(1)).onPackageDisappeared(eq(FAKE_PACKAGE_NAME),
eq(PackageMonitor.PACKAGE_PERMANENT_CHANGE));
verify(spyPackageMonitor, times(1)).onSomePackagesChanged();
@@ -316,6 +363,19 @@
verify(spyPackageMonitor, times(1))
.onPackageUpdateFinished(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
verify(spyPackageMonitor, times(1)).onPackageModified(eq(FAKE_PACKAGE_NAME));
+
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1)).onPackageAppearedWithExtras(eq(FAKE_PACKAGE_NAME),
+ argumentCaptor.capture());
+ Bundle capturedExtras = argumentCaptor.getValue();
+ Bundle expectedExtras = intent.getExtras();
+ assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_UID))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REPLACING))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REPLACING));
+
verify(spyPackageMonitor, times(1))
.onPackageAppeared(eq(FAKE_PACKAGE_NAME), eq(PackageMonitor.PACKAGE_UPDATING));
verify(spyPackageMonitor, times(1)).onSomePackagesChanged();
@@ -336,6 +396,19 @@
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
verify(spyPackageMonitor, times(1))
.onPackageAdded(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
+
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1)).onPackageAppearedWithExtras(eq(FAKE_PACKAGE_NAME),
+ argumentCaptor.capture());
+ Bundle capturedExtras = argumentCaptor.getValue();
+ Bundle expectedExtras = intent.getExtras();
+ assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_UID))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID));
+ assertThat(capturedExtras.getInt(Intent.EXTRA_REPLACING))
+ .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REPLACING));
+
verify(spyPackageMonitor, times(1)).onPackageAppeared(eq(FAKE_PACKAGE_NAME),
eq(PackageMonitor.PACKAGE_PERMANENT_CHANGE));
verify(spyPackageMonitor, times(1)).onSomePackagesChanged();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index f8dd208..09ba4f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -37,6 +37,7 @@
import android.view.WindowManager.TRANSIT_NONE
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_TO_FRONT
+import android.window.RemoteTransition
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
@@ -65,7 +66,9 @@
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.ShellSharedConstants
+import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.transition.Transitions.TransitionHandler
import com.android.wm.shell.util.KtProtoLog
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
@@ -139,20 +142,22 @@
}
/** Show all tasks, that are part of the desktop, on top of launcher */
- fun showDesktopApps(displayId: Int) {
+ fun showDesktopApps(displayId: Int, remoteTransition: RemoteTransition? = null) {
KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: showDesktopApps")
val wct = WindowContainerTransaction()
- // TODO(b/278084491): pass in display id
bringDesktopAppsToFront(displayId, wct)
- // Execute transaction if there are pending operations
- if (!wct.isEmpty) {
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- // TODO(b/268662477): add animation for the transition
- transitions.startTransition(TRANSIT_NONE, wct, null /* handler */)
- } else {
- shellTaskOrganizer.applyTransaction(wct)
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ // TODO(b/255649902): ensure remote transition is supplied once state is introduced
+ val transitionType = if (remoteTransition == null) TRANSIT_NONE else TRANSIT_TO_FRONT
+ val handler = remoteTransition?.let {
+ OneShotRemoteHandler(transitions.mainExecutor, remoteTransition)
}
+ transitions.startTransition(transitionType, wct, handler).also { t ->
+ handler?.setTransition(t)
+ }
+ } else {
+ shellTaskOrganizer.applyTransaction(wct)
}
}
@@ -1093,11 +1098,11 @@
controller = null
}
- override fun showDesktopApps(displayId: Int) {
+ override fun showDesktopApps(displayId: Int, remoteTransition: RemoteTransition?) {
ExecutorUtils.executeRemoteCallWithTaskPermission(
controller,
"showDesktopApps"
- ) { c -> c.showDesktopApps(displayId) }
+ ) { c -> c.showDesktopApps(displayId, remoteTransition) }
}
override fun stashDesktopApps(displayId: Int) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl
index 47edfd4..6bdaf1e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl
@@ -17,6 +17,7 @@
package com.android.wm.shell.desktopmode;
import android.app.ActivityManager.RunningTaskInfo;
+import android.window.RemoteTransition;
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
/**
@@ -25,7 +26,7 @@
interface IDesktopMode {
/** Show apps on the desktop on the given display */
- void showDesktopApps(int displayId);
+ void showDesktopApps(int displayId, in RemoteTransition remoteTransition);
/** Stash apps on the desktop to allow launching another app from home screen */
void stashDesktopApps(int displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
index 0d77a2e..ef8393c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
@@ -29,12 +29,16 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Handler;
+import android.os.Looper;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewTreeObserver;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.concurrent.Executor;
/**
@@ -74,6 +78,7 @@
private final TaskViewTaskController mTaskViewTaskController;
private Region mObscuredTouchRegion;
private Insets mCaptionInsets;
+ private Handler mHandler;
public TaskView(Context context, TaskViewTaskController taskViewTaskController) {
super(context, null, 0, 0, true /* disableBackgroundLayer */);
@@ -81,6 +86,7 @@
// TODO(b/266736992): Think about a better way to set the TaskViewBase on the
// TaskViewTaskController and vice-versa
mTaskViewTaskController.setTaskViewBase(this);
+ mHandler = Handler.getMain();
getHolder().addCallback(this);
}
@@ -117,14 +123,16 @@
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
onLocationChanged();
if (taskInfo.taskDescription != null) {
- setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+ final int bgColor = taskInfo.taskDescription.getBackgroundColor();
+ runOnViewThread(() -> setResizeBackgroundColor(bgColor));
}
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
if (taskInfo.taskDescription != null) {
- setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+ final int bgColor = taskInfo.taskDescription.getBackgroundColor();
+ runOnViewThread(() -> setResizeBackgroundColor(bgColor));
}
}
@@ -143,7 +151,7 @@
@Override
public void setResizeBgColor(SurfaceControl.Transaction t, int bgColor) {
- setResizeBackgroundColor(t, bgColor);
+ runOnViewThread(() -> setResizeBackgroundColor(t, bgColor));
}
/**
@@ -272,12 +280,14 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+ mHandler = getHandler();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+ mHandler = Handler.getMain();
}
/** Returns the task info for the task in the TaskView. */
@@ -285,4 +295,24 @@
public ActivityManager.RunningTaskInfo getTaskInfo() {
return mTaskViewTaskController.getTaskInfo();
}
+
+ /**
+ * Sets the handler, only for testing.
+ */
+ @VisibleForTesting
+ void setHandler(Handler viewHandler) {
+ mHandler = viewHandler;
+ }
+
+ /**
+ * Ensures that the given runnable runs on the view's thread.
+ */
+ private void runOnViewThread(Runnable r) {
+ if (mHandler.getLooper().isCurrentThread()) {
+ r.run();
+ } else {
+ // If this call is not from the same thread as the view, then post it
+ mHandler.post(r);
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRemoteTransition.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRemoteTransition.java
new file mode 100644
index 0000000..0df42b3
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRemoteTransition.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.wm.shell;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.SurfaceControl;
+import android.window.IRemoteTransition;
+import android.window.IRemoteTransitionFinishedCallback;
+import android.window.TransitionInfo;
+import android.window.WindowContainerTransaction;
+
+/**
+ * {@link IRemoteTransition} for testing purposes.
+ * Stores info about
+ * {@link #startAnimation(IBinder, TransitionInfo, SurfaceControl.Transaction,
+ * IRemoteTransitionFinishedCallback)} being called.
+ */
+public class TestRemoteTransition extends IRemoteTransition.Stub {
+ private boolean mCalled = false;
+ final WindowContainerTransaction mRemoteFinishWCT = new WindowContainerTransaction();
+
+ @Override
+ public void startAnimation(IBinder transition, TransitionInfo info,
+ SurfaceControl.Transaction startTransaction,
+ IRemoteTransitionFinishedCallback finishCallback)
+ throws RemoteException {
+ mCalled = true;
+ finishCallback.onTransitionFinished(mRemoteFinishWCT, null /* sct */);
+ }
+
+ @Override
+ public void mergeAnimation(IBinder transition, TransitionInfo info,
+ SurfaceControl.Transaction t, IBinder mergeTarget,
+ IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+ }
+
+ /**
+ * Check whether this remote transition
+ * {@link #startAnimation(IBinder, TransitionInfo, SurfaceControl.Transaction,
+ * IRemoteTransitionFinishedCallback)} is called
+ */
+ public boolean isCalled() {
+ return mCalled;
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index c6cccc0..664fbb2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -28,10 +28,10 @@
import android.view.Display.DEFAULT_DISPLAY
import android.view.WindowManager
import android.view.WindowManager.TRANSIT_CHANGE
-import android.view.WindowManager.TRANSIT_NONE
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.DisplayAreaInfo
+import android.window.RemoteTransition
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
@@ -43,6 +43,7 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestRemoteTransition
import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.common.DisplayController
@@ -57,8 +58,10 @@
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
+import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS
+import com.android.wm.shell.transition.Transitions.TransitionHandler
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
@@ -69,6 +72,7 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.eq
+import org.mockito.ArgumentMatchers.isA
import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
import org.mockito.Mockito
@@ -174,9 +178,9 @@
markTaskHidden(task1)
markTaskHidden(task2)
- controller.showDesktopApps(DEFAULT_DISPLAY)
+ controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(expectTransition = TRANSIT_NONE)
+ val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
@@ -192,9 +196,9 @@
markTaskVisible(task1)
markTaskVisible(task2)
- controller.showDesktopApps(DEFAULT_DISPLAY)
+ controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(expectTransition = TRANSIT_NONE)
+ val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
@@ -210,9 +214,9 @@
markTaskHidden(task1)
markTaskVisible(task2)
- controller.showDesktopApps(DEFAULT_DISPLAY)
+ controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(expectTransition = TRANSIT_NONE)
+ val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
@@ -224,9 +228,9 @@
fun showDesktopApps_noActiveTasks_reorderHomeToTop() {
val homeTask = setUpHomeTask()
- controller.showDesktopApps(DEFAULT_DISPLAY)
+ controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(expectTransition = TRANSIT_NONE)
+ val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(1)
wct.assertReorderAt(index = 0, homeTask)
}
@@ -240,9 +244,9 @@
markTaskHidden(taskDefaultDisplay)
markTaskHidden(taskSecondDisplay)
- controller.showDesktopApps(DEFAULT_DISPLAY)
+ controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(expectTransition = TRANSIT_NONE)
+ val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(2)
// Expect order to be from bottom: home, task
wct.assertReorderAt(index = 0, homeTaskDefaultDisplay)
@@ -373,7 +377,7 @@
val task = setUpFreeformTask()
task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FULLSCREEN
controller.moveToFullscreen(task)
- val wct = getLatestWct(expectTransition = TRANSIT_CHANGE)
+ val wct = getLatestWct(type = TRANSIT_CHANGE)
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
.isEqualTo(WINDOWING_MODE_UNDEFINED)
}
@@ -383,7 +387,7 @@
val task = setUpFreeformTask()
task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FREEFORM
controller.moveToFullscreen(task)
- val wct = getLatestWct(expectTransition = TRANSIT_CHANGE)
+ val wct = getLatestWct(type = TRANSIT_CHANGE)
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
.isEqualTo(WINDOWING_MODE_FULLSCREEN)
}
@@ -401,7 +405,7 @@
controller.moveToFullscreen(taskDefaultDisplay)
- with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
+ with(getLatestWct(type = TRANSIT_CHANGE)) {
assertThat(changes.keys).contains(taskDefaultDisplay.token.asBinder())
assertThat(changes.keys).doesNotContain(taskSecondDisplay.token.asBinder())
}
@@ -414,7 +418,7 @@
controller.moveTaskToFront(task1)
- val wct = getLatestWct(expectTransition = TRANSIT_TO_FRONT)
+ val wct = getLatestWct(type = TRANSIT_TO_FRONT)
assertThat(wct.hierarchyOps).hasSize(1)
wct.assertReorderAt(index = 0, task1)
}
@@ -439,7 +443,7 @@
val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
controller.moveToNextDisplay(task.taskId)
- with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
+ with(getLatestWct(type = TRANSIT_CHANGE)) {
assertThat(hierarchyOps).hasSize(1)
assertThat(hierarchyOps[0].container).isEqualTo(task.token.asBinder())
assertThat(hierarchyOps[0].isReparent).isTrue()
@@ -461,7 +465,7 @@
val task = setUpFreeformTask(displayId = SECOND_DISPLAY)
controller.moveToNextDisplay(task.taskId)
- with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
+ with(getLatestWct(type = TRANSIT_CHANGE)) {
assertThat(hierarchyOps).hasSize(1)
assertThat(hierarchyOps[0].container).isEqualTo(task.token.asBinder())
assertThat(hierarchyOps[0].isReparent).isTrue()
@@ -747,11 +751,16 @@
}
private fun getLatestWct(
- @WindowManager.TransitionType expectTransition: Int = TRANSIT_OPEN
+ @WindowManager.TransitionType type: Int = TRANSIT_OPEN,
+ handlerClass: Class<out TransitionHandler>? = null
): WindowContainerTransaction {
val arg = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
if (ENABLE_SHELL_TRANSITIONS) {
- verify(transitions).startTransition(eq(expectTransition), arg.capture(), isNull())
+ if (handlerClass == null) {
+ verify(transitions).startTransition(eq(type), arg.capture(), isNull())
+ } else {
+ verify(transitions).startTransition(eq(type), arg.capture(), isA(handlerClass))
+ }
} else {
verify(shellTaskOrganizer).applyTransaction(arg.capture())
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index 5efd9ad..d542139 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -47,11 +47,8 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.os.IBinder;
-import android.os.RemoteException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import android.window.IRemoteTransition;
-import android.window.IRemoteTransitionFinishedCallback;
import android.window.RemoteTransition;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
@@ -65,6 +62,7 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestRemoteTransition;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.TransitionInfoBuilder;
import com.android.wm.shell.common.DisplayController;
@@ -205,7 +203,7 @@
// Make sure split-screen is now visible
assertTrue(mStageCoordinator.isSplitScreenVisible());
- assertTrue(testRemote.mCalled);
+ assertTrue(testRemote.isCalled());
}
@Test
@@ -468,24 +466,4 @@
return out;
}
- class TestRemoteTransition extends IRemoteTransition.Stub {
- boolean mCalled = false;
- final WindowContainerTransaction mRemoteFinishWCT = new WindowContainerTransaction();
-
- @Override
- public void startAnimation(IBinder transition, TransitionInfo info,
- SurfaceControl.Transaction startTransaction,
- IRemoteTransitionFinishedCallback finishCallback)
- throws RemoteException {
- mCalled = true;
- finishCallback.onTransitionFinished(mRemoteFinishWCT, null /* sct */);
- }
-
- @Override
- public void mergeAnimation(IBinder transition, TransitionInfo info,
- SurfaceControl.Transaction t, IBinder mergeTarget,
- IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
- }
- }
-
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index 0088051..4afb29e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -43,6 +43,8 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Handler;
+import android.os.Looper;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.SurfaceControl;
@@ -88,6 +90,10 @@
SyncTransactionQueue mSyncQueue;
@Mock
Transitions mTransitions;
+ @Mock
+ Looper mViewLooper;
+ @Mock
+ Handler mViewHandler;
SurfaceSession mSession;
SurfaceControl mLeash;
@@ -105,6 +111,8 @@
.build();
mContext = getContext();
+ doReturn(true).when(mViewLooper).isCurrentThread();
+ doReturn(mViewLooper).when(mViewHandler).getLooper();
mTaskInfo = new ActivityManager.RunningTaskInfo();
mTaskInfo.token = mToken;
@@ -132,6 +140,7 @@
mTaskViewTaskController = spy(new TaskViewTaskController(mContext, mOrganizer,
mTaskViewTransitions, mSyncQueue));
mTaskView = new TaskView(mContext, mTaskViewTaskController);
+ mTaskView.setHandler(mViewHandler);
mTaskView.setListener(mExecutor, mViewListener);
}
@@ -646,4 +655,17 @@
assertThat(mTaskViewTaskController.getTaskInfo()).isNull();
}
+
+ @Test
+ public void testOnTaskInfoChangedOnSameUiThread() {
+ mTaskViewTaskController.onTaskInfoChanged(mTaskInfo);
+ verify(mViewHandler, never()).post(any());
+ }
+
+ @Test
+ public void testOnTaskInfoChangedOnDifferentUiThread() {
+ doReturn(false).when(mViewLooper).isCurrentThread();
+ mTaskViewTaskController.onTaskInfoChanged(mTaskInfo);
+ verify(mViewHandler).post(any());
+ }
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 9924fae..09f09b9 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -2409,13 +2409,16 @@
@RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER)
@Nullable
public Descrambler openDescrambler() {
+ acquireTRMSLock("openDescrambler()");
mDemuxLock.lock();
try {
- if (!checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX, mDemuxLock)) {
+ // no need to unlock mDemuxLock (so pass null instead) as TRMS lock is already acquired
+ if (!checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX, null)) {
return null;
}
return requestDescrambler();
} finally {
+ releaseTRMSLock();
mDemuxLock.unlock();
}
}
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index af6fa86..5c2f979 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -131,5 +131,22 @@
}
]
}
+ ],
+ // v2/sysui/suite/test-mapping-sysui-screenshot-test
+ "sysui-screenshot-test": [
+ {
+ "name": "SystemUIGoogleScreenshotTests",
+ "options": [
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ }
+ ]
+ }
]
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index 8e34008..519c0a9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -39,7 +39,9 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.android.compose.animation.scene.ElementKey
@@ -166,11 +168,18 @@
modifier =
Modifier.align(Alignment.CenterVertically)
// use graphicsLayer instead of Modifier.scale to anchor transform to
- // top left corner
+ // the (start, top) corner
.graphicsLayer(
scaleX = 2.57f,
scaleY = 2.57f,
- transformOrigin = TransformOrigin(0f, 0.5f)
+ transformOrigin =
+ TransformOrigin(
+ when (LocalLayoutDirection.current) {
+ LayoutDirection.Ltr -> 0f
+ LayoutDirection.Rtl -> 1f
+ },
+ 0.5f
+ )
),
)
Spacer(modifier = Modifier.weight(1f))
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 46d3c8a..79d9c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -1096,8 +1096,19 @@
// cancel the fingerprint scan.
mCancelAodFingerUpAction = mFgExecutor.executeDelayed(this::tryAodSendFingerUp,
AOD_SEND_FINGER_UP_DELAY_MILLIS);
- // using a hard-coded value for major and minor until it is available from the sensor
- onFingerDown(requestId, screenX, screenY, minor, major);
+ // using a hard-coded value for orientation, time and gestureStart until they are
+ // available from the sensor.
+ onFingerDown(
+ requestId,
+ MotionEvent.INVALID_POINTER_ID /* pointerId */,
+ screenX,
+ screenY,
+ minor,
+ major,
+ 0f /* orientation */,
+ 0L /* time */,
+ 0L /* gestureStart */,
+ true /* isAod */);
};
if (mScreenOn) {
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index e489499..ce9d6fd 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -37,7 +37,6 @@
import com.android.internal.util.UserIcons
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.res.R
import com.android.systemui.SystemUISecondaryUserService
import com.android.systemui.animation.Expandable
import com.android.systemui.broadcast.BroadcastDispatcher
@@ -50,6 +49,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.user.UserSwitchDialogController
+import com.android.systemui.res.R
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
import com.android.systemui.user.CreateUserActivity
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
@@ -62,6 +62,7 @@
import com.android.systemui.user.utils.MultiUserActionsEvent
import com.android.systemui.user.utils.MultiUserActionsEventHelper
import com.android.systemui.util.kotlin.pairwise
+import com.android.systemui.utils.UserRestrictionChecker
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -103,6 +104,7 @@
private val refreshUsersScheduler: RefreshUsersScheduler,
private val guestUserInteractor: GuestUserInteractor,
private val uiEventLogger: UiEventLogger,
+ private val userRestrictionChecker: UserRestrictionChecker,
) {
/**
* Defines interface for classes that can be notified when the state of users on the device is
@@ -593,6 +595,7 @@
) &&
// If the user is auto-created is must not be currently resetting.
!(isGuestUserAutoCreated && isGuestUserResetting),
+ userRestrictionChecker = userRestrictionChecker,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt
index 93573fa..80139bd 100644
--- a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/data/LegacyUserDataHelper.kt
@@ -22,10 +22,10 @@
import android.graphics.Bitmap
import android.os.UserManager
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
-import com.android.settingslib.RestrictedLockUtilsInternal
import com.android.systemui.res.R
import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.user.shared.model.UserActionModel
+import com.android.systemui.utils.UserRestrictionChecker
/**
* Defines utility functions for helping with legacy data code for users.
@@ -68,6 +68,7 @@
actionType: UserActionModel,
isRestricted: Boolean,
isSwitchToEnabled: Boolean,
+ userRestrictionChecker: UserRestrictionChecker,
): UserRecord {
return UserRecord(
isGuest = actionType == UserActionModel.ENTER_GUEST_MODE,
@@ -79,6 +80,7 @@
getEnforcedAdmin(
context = context,
selectedUserId = selectedUserId,
+ userRestrictionChecker = userRestrictionChecker,
),
isManageUsers = actionType == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
)
@@ -103,9 +105,10 @@
private fun getEnforcedAdmin(
context: Context,
selectedUserId: Int,
+ userRestrictionChecker: UserRestrictionChecker
): EnforcedAdmin? {
val admin =
- RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+ userRestrictionChecker.checkIfRestrictionEnforced(
context,
UserManager.DISALLOW_ADD_USER,
selectedUserId,
@@ -113,7 +116,7 @@
?: return null
return if (
- !RestrictedLockUtilsInternal.hasBaseUserRestriction(
+ !userRestrictionChecker.hasBaseUserRestriction(
context,
UserManager.DISALLOW_ADD_USER,
selectedUserId,
diff --git a/packages/SystemUI/src/com/android/systemui/utils/UserRestrictionChecker.kt b/packages/SystemUI/src/com/android/systemui/utils/UserRestrictionChecker.kt
new file mode 100644
index 0000000..3f8346b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/utils/UserRestrictionChecker.kt
@@ -0,0 +1,25 @@
+package com.android.systemui.utils
+
+import android.content.Context
+import com.android.settingslib.RestrictedLockUtils
+import com.android.settingslib.RestrictedLockUtilsInternal
+import javax.inject.Inject
+
+/** Proxy to call [RestrictedLockUtilsInternal] */
+class UserRestrictionChecker @Inject constructor() {
+ fun checkIfRestrictionEnforced(
+ context: Context,
+ userRestriction: String,
+ userId: Int
+ ): RestrictedLockUtils.EnforcedAdmin? {
+ return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+ context,
+ userRestriction,
+ userId
+ )
+ }
+
+ fun hasBaseUserRestriction(context: Context, userRestriction: String, userId: Int): Boolean {
+ return RestrictedLockUtilsInternal.hasBaseUserRestriction(context, userRestriction, userId)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
index 8fc63b2..7365460 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
@@ -44,6 +44,7 @@
import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
import com.android.systemui.user.domain.interactor.UserInteractor
+import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -126,6 +127,7 @@
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor = guestInteractor,
uiEventLogger = uiEventLogger,
+ userRestrictionChecker = mock(),
)
shadeInteractor =
ShadeInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
index d018cbb..2be1c09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
@@ -25,7 +25,6 @@
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
@@ -35,6 +34,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.res.R
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.shared.model.ObservableTransitionState
@@ -54,6 +54,7 @@
import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
import com.android.systemui.user.domain.interactor.UserInteractor
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -153,6 +154,7 @@
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor = guestInteractor,
uiEventLogger = uiEventLogger,
+ userRestrictionChecker = mock(),
)
underTest =
ShadeInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index bbc49c8..af941d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -34,7 +34,6 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
-import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Text
@@ -45,6 +44,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.user.UserSwitchDialogController
+import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -1120,6 +1120,7 @@
),
uiEventLogger = uiEventLogger,
featureFlags = featureFlags,
+ userRestrictionChecker = mock(),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 2433e12..a8db368 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -267,6 +267,7 @@
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
+ userRestrictionChecker = mock(),
)
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 8c88f95..6932f5e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -45,6 +45,7 @@
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
import com.android.systemui.user.shared.model.UserActionModel
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -176,6 +177,7 @@
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
+ userRestrictionChecker = mock(),
),
guestUserInteractor = guestUserInteractor,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
index ceab8e9..945aaed 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
@@ -50,6 +50,7 @@
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.utils.UserRestrictionChecker
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.test.TestScope
import org.mockito.Mockito.mock
@@ -137,6 +138,7 @@
refreshUsersScheduler = mock(RefreshUsersScheduler::class.java),
guestUserInteractor = mock(GuestUserInteractor::class.java),
uiEventLogger = mock(UiEventLogger::class.java),
+ userRestrictionChecker = mock(UserRestrictionChecker::class.java),
)
return WithDependencies(
trustRepository = trustRepository,
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index 0480c22..11189cf 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -25,5 +25,12 @@
name: "send_a11y_events_based_on_state"
namespace: "accessibility"
description: "Sends accessibility events in TouchExplorer#onAccessibilityEvent based on internal state to keep it consistent. This reduces test flakiness."
-bug: "295575684"
-}
\ No newline at end of file
+ bug: "295575684"
+}
+
+flag {
+ name: "add_window_token_without_lock"
+ namespace: "accessibility"
+ description: "Calls WMS.addWindowToken without holding A11yManagerService#mLock"
+ bug: "297972548"
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 05b6eb4..fa73cff 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -1506,11 +1506,17 @@
}
}
- public void onAdded() {
+ /**
+ * Called when the connection is first created. Add a window token for all known displays.
+ * <p>
+ * <strong>Note:</strong> Should not be called while holding the AccessibilityManagerService
+ * lock because this calls out to WindowManagerService.
+ */
+ void addWindowTokensForAllDisplays() {
final Display[] displays = mDisplayManager.getDisplays();
for (int i = 0; i < displays.length; i++) {
final int displayId = displays[i].getDisplayId();
- onDisplayAdded(displayId);
+ addWindowTokenForDisplay(displayId);
}
}
@@ -1518,9 +1524,13 @@
* Called whenever a logical display has been added to the system. Add a window token for adding
* an accessibility overlay.
*
+ * <p>
+ * <strong>Note:</strong> Should not be called while holding the AccessibilityManagerService
+ * lock because this calls out to WindowManagerService.
+ *
* @param displayId The id of the logical display that was added.
*/
- public void onDisplayAdded(int displayId) {
+ void addWindowTokenForDisplay(int displayId) {
final long identity = Binder.clearCallingIdentity();
try {
final IBinder overlayWindowToken = new Binder();
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 93ba362..60d4ee6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -154,6 +154,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IntPair;
+import com.android.internal.util.Preconditions;
import com.android.server.AccessibilityManagerInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -4500,6 +4501,20 @@
private int mSystemUiUid = 0;
AccessibilityDisplayListener(Context context, Handler handler) {
+ if (Flags.addWindowTokenWithoutLock()) {
+ // Avoid concerns about one thread adding displays while another thread removes
+ // them by ensuring the looper is the main looper and the DisplayListener
+ // callbacks are always executed on the one main thread.
+ final boolean isMainHandler = handler.getLooper() == Looper.getMainLooper();
+ final String errorMessage =
+ "AccessibilityDisplayListener must use the main handler";
+ if (Build.IS_USERDEBUG || Build.IS_ENG) {
+ Preconditions.checkArgument(isMainHandler, errorMessage);
+ } else if (!isMainHandler) {
+ Slog.e(LOG_TAG, errorMessage);
+ }
+ }
+
mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(this, handler);
initializeDisplayList();
@@ -4541,11 +4556,21 @@
@Override
public void onDisplayAdded(int displayId) {
+ if (Flags.addWindowTokenWithoutLock()) {
+ final boolean isMainThread = Looper.getMainLooper().isCurrentThread();
+ final String errorMessage = "onDisplayAdded must be called from the main thread";
+ if (Build.IS_USERDEBUG || Build.IS_ENG) {
+ Preconditions.checkArgument(isMainThread, errorMessage);
+ } else if (!isMainThread) {
+ Slog.e(LOG_TAG, errorMessage);
+ }
+ }
final Display display = mDisplayManager.getDisplay(displayId);
if (!isValidDisplay(display)) {
return;
}
+ final List<AccessibilityServiceConnection> services;
synchronized (mLock) {
mDisplaysList.add(display);
mA11yOverlayLayers.put(
@@ -4554,21 +4579,42 @@
mInputFilter.onDisplayAdded(display);
}
AccessibilityUserState userState = getCurrentUserStateLocked();
- if (displayId != Display.DEFAULT_DISPLAY) {
- final List<AccessibilityServiceConnection> services = userState.mBoundServices;
- for (int i = 0; i < services.size(); i++) {
- AccessibilityServiceConnection boundClient = services.get(i);
- boundClient.onDisplayAdded(displayId);
+ if (Flags.addWindowTokenWithoutLock()) {
+ services = new ArrayList<>(userState.mBoundServices);
+ } else {
+ services = userState.mBoundServices;
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ for (int i = 0; i < services.size(); i++) {
+ AccessibilityServiceConnection boundClient = services.get(i);
+ boundClient.addWindowTokenForDisplay(displayId);
+ }
}
}
updateMagnificationLocked(userState);
updateWindowsForAccessibilityCallbackLocked(userState);
notifyClearAccessibilityCacheLocked();
}
+ if (Flags.addWindowTokenWithoutLock()) {
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ for (int i = 0; i < services.size(); i++) {
+ AccessibilityServiceConnection boundClient = services.get(i);
+ boundClient.addWindowTokenForDisplay(displayId);
+ }
+ }
+ }
}
@Override
public void onDisplayRemoved(int displayId) {
+ if (Flags.addWindowTokenWithoutLock()) {
+ final boolean isMainThread = Looper.getMainLooper().isCurrentThread();
+ final String errorMessage = "onDisplayRemoved must be called from the main thread";
+ if (Build.IS_USERDEBUG || Build.IS_ENG) {
+ Preconditions.checkArgument(isMainThread, errorMessage);
+ } else if (!isMainThread) {
+ Slog.e(LOG_TAG, errorMessage);
+ }
+ }
synchronized (mLock) {
if (!removeDisplayFromList(displayId)) {
return;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 9e70073..7a2a602 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -44,7 +44,6 @@
import android.view.Display;
import android.view.MotionEvent;
-
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -169,6 +168,10 @@
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
+ AccessibilityUserState userState = mUserStateWeakReference.get();
+ if (userState != null && Flags.addWindowTokenWithoutLock()) {
+ addWindowTokensForAllDisplays();
+ }
synchronized (mLock) {
if (mService != service) {
if (mService != null) {
@@ -184,7 +187,6 @@
}
}
mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
- AccessibilityUserState userState = mUserStateWeakReference.get();
if (userState == null) return;
userState.addServiceLocked(this);
mSystemSupport.onClientChangeLocked(false);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index ab6cc71..693526a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -224,7 +224,9 @@
void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
if (!mBoundServices.contains(serviceConnection)) {
- serviceConnection.onAdded();
+ if (!Flags.addWindowTokenWithoutLock()) {
+ serviceConnection.addWindowTokensForAllDisplays();
+ }
mBoundServices.add(serviceConnection);
mComponentNameToServiceMap.put(serviceConnection.getComponentName(), serviceConnection);
mServiceInfoChangeListener.onServiceInfoChangedLocked(this);
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 208acdf..53c629a 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -25,9 +25,11 @@
import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
+import android.os.Looper;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.util.Slog;
@@ -35,6 +37,7 @@
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
import com.android.server.utils.Slogf;
import com.android.server.wm.WindowManagerInternal;
@@ -98,46 +101,47 @@
accessibilityServiceInfo.setComponentName(COMPONENT_NAME);
Slogf.i(LOG_TAG, "Registering UiTestAutomationService (id=%s) when called by user %d",
accessibilityServiceInfo.getId(), Binder.getCallingUserHandle().getIdentifier());
- synchronized (mLock) {
- if (mUiAutomationService != null) {
- throw new IllegalStateException(
- "UiAutomationService " + mUiAutomationService.mServiceInterface
- + "already registered!");
- }
-
- try {
- owner.linkToDeath(mUiAutomationServiceOwnerDeathRecipient, 0);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Couldn't register for the death of a UiTestAutomationService!",
- re);
- return;
- }
-
- mUiAutomationFlags = flags;
- mSystemSupport = systemSupport;
- // Ignore registering UiAutomation if it is not allowed to use the accessibility
- // subsystem.
- if (!useAccessibility()) {
- return;
- }
- mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id,
- mainHandler, mLock, securityPolicy, systemSupport, trace, windowManagerInternal,
- systemActionPerformer, awm);
- mUiAutomationServiceOwner = owner;
- mUiAutomationService.mServiceInterface = serviceClient;
- try {
- mUiAutomationService.mServiceInterface.asBinder().linkToDeath(mUiAutomationService,
- 0);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Failed registering death link: " + re);
- destroyUiAutomationService();
- return;
- }
-
- mUiAutomationService.onAdded();
-
- mUiAutomationService.connectServiceUnknownThread();
+ if (mUiAutomationService != null) {
+ throw new IllegalStateException(
+ "UiAutomationService " + mUiAutomationService.mServiceInterface
+ + "already registered!");
}
+
+ try {
+ owner.linkToDeath(mUiAutomationServiceOwnerDeathRecipient, 0);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Couldn't register for the death of a UiTestAutomationService!",
+ re);
+ return;
+ }
+
+ mUiAutomationFlags = flags;
+ mSystemSupport = systemSupport;
+ // Ignore registering UiAutomation if it is not allowed to use the accessibility
+ // subsystem.
+ if (!useAccessibility()) {
+ return;
+ }
+ mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id,
+ mainHandler, mLock, securityPolicy, systemSupport, trace, windowManagerInternal,
+ systemActionPerformer, awm);
+ mUiAutomationServiceOwner = owner;
+ mUiAutomationService.mServiceInterface = serviceClient;
+ try {
+ mUiAutomationService.mServiceInterface.asBinder().linkToDeath(mUiAutomationService,
+ 0);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Failed registering death link: " + re);
+ destroyUiAutomationService();
+ return;
+ }
+
+ if (!Flags.addWindowTokenWithoutLock()) {
+ mUiAutomationService.addWindowTokensForAllDisplays();
+ }
+ // UiAutomationService#connectServiceUnknownThread posts to a handler
+ // so this call should return immediately.
+ mUiAutomationService.connectServiceUnknownThread();
}
void unregisterUiTestAutomationServiceLocked(IAccessibilityServiceClient serviceClient) {
@@ -253,6 +257,13 @@
super(context, COMPONENT_NAME, accessibilityServiceInfo, id, mainHandler, lock,
securityPolicy, systemSupport, trace, windowManagerInternal,
systemActionPerformer, awm);
+ final boolean isMainHandler = mainHandler.getLooper() == Looper.getMainLooper();
+ final String errorMessage = "UiAutomationService must use the main handler";
+ if (Build.IS_USERDEBUG || Build.IS_ENG) {
+ Preconditions.checkArgument(isMainHandler, errorMessage);
+ } else if (!isMainHandler) {
+ Slog.e(LOG_TAG, errorMessage);
+ }
mMainHandler = mainHandler;
setDisplayTypes(DISPLAY_TYPE_DEFAULT | DISPLAY_TYPE_PROXY);
}
@@ -274,6 +285,9 @@
// If the serviceInterface is null, the UiAutomation has been shut down on
// another thread.
if (serviceInterface != null) {
+ if (Flags.addWindowTokenWithoutLock()) {
+ mUiAutomationService.addWindowTokensForAllDisplays();
+ }
if (mTrace.isA11yTracingEnabledForTypes(
AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT)) {
mTrace.logTrace("UiAutomationService.connectServiceUnknownThread",
@@ -286,7 +300,7 @@
mOverlayWindowTokens.get(Display.DEFAULT_DISPLAY));
}
} catch (RemoteException re) {
- Slog.w(LOG_TAG, "Error initialized connection", re);
+ Slog.w(LOG_TAG, "Error initializing connection", re);
destroyUiAutomationService();
}
});
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
index e8839a2..720687e 100644
--- a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
@@ -562,7 +562,8 @@
private byte[] constructToken(D2DHandshakeContext.Role role, byte[] authValue)
throws GeneralSecurityException {
MessageDigest hash = MessageDigest.getInstance("SHA-256");
- byte[] roleUtf8 = role.name().getBytes(StandardCharsets.UTF_8);
+ String roleName = role == Role.INITIATOR ? "Initiator" : "Responder";
+ byte[] roleUtf8 = roleName.getBytes(StandardCharsets.UTF_8);
int tokenLength = roleUtf8.length + authValue.length;
return hash.digest(ByteBuffer.allocate(tokenLength)
.put(roleUtf8)
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 5fa0ffa..6005b64 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1442,7 +1442,6 @@
uidRec.setFrozen(false);
postUidFrozenMessage(uidRec.getUid(), false);
}
- reportProcessFreezableChangedLocked(app);
opt.setFreezerOverride(false);
if (pid == 0 || !opt.isFrozen()) {
@@ -1481,6 +1480,7 @@
if (processKilled) {
return;
}
+ reportProcessFreezableChangedLocked(app);
long freezeTime = opt.getFreezeUnfreezeTime();
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3d11c68..0615ecf 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3087,6 +3087,8 @@
if (old == proc && proc.isPersistent()) {
// We are re-adding a persistent process. Whatevs! Just leave it there.
Slog.w(TAG, "Re-adding persistent process " + proc);
+ // Ensure that the mCrashing flag is cleared, since this is a restart
+ proc.resetCrashingOnRestart();
} else if (old != null) {
if (old.isKilled()) {
// The old process has been killed, we probably haven't had
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index cfbb5a5..d8a2695 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -618,6 +618,10 @@
mPkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
}
+ void resetCrashingOnRestart() {
+ mErrorState.setCrashing(false);
+ }
+
@GuardedBy(anyOf = {"mService", "mProcLock"})
UidRecord getUidRecord() {
return mUidRecord;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 52eef47..b9464d9 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -18,9 +18,6 @@
import static android.app.AppGlobals.getPackageManager;
import static android.content.Intent.ACTION_OVERLAY_CHANGED;
-import static android.content.Intent.ACTION_PACKAGE_ADDED;
-import static android.content.Intent.ACTION_PACKAGE_CHANGED;
-import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
@@ -31,10 +28,10 @@
import static android.content.om.OverlayManagerTransaction.Request.TYPE_SET_ENABLED;
import static android.content.om.OverlayManagerTransaction.Request.TYPE_UNREGISTER_FABRICATED;
import static android.content.pm.PackageManager.SIGNATURE_MATCH;
+import static android.os.Process.INVALID_UID;
import static android.os.Trace.TRACE_TAG_RRO;
import static android.os.Trace.traceBegin;
import static android.os.Trace.traceEnd;
-
import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;
import android.annotation.NonNull;
@@ -82,6 +79,7 @@
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.content.om.OverlayConfig;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -261,6 +259,8 @@
private final OverlayActorEnforcer mActorEnforcer;
+ private final PackageMonitor mPackageMonitor = new OverlayManagerPackageMonitor();
+
private int mPrevStartedUserId = -1;
public OverlayManagerService(@NonNull final Context context) {
@@ -277,16 +277,9 @@
OverlayConfig.getSystemInstance(), getDefaultOverlayPackages());
mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
- HandlerThread packageReceiverThread = new HandlerThread(TAG);
- packageReceiverThread.start();
-
- final IntentFilter packageFilter = new IntentFilter();
- packageFilter.addAction(ACTION_PACKAGE_ADDED);
- packageFilter.addAction(ACTION_PACKAGE_CHANGED);
- packageFilter.addAction(ACTION_PACKAGE_REMOVED);
- packageFilter.addDataScheme("package");
- getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
- packageFilter, null, packageReceiverThread.getThreadHandler());
+ HandlerThread packageMonitorThread = new HandlerThread(TAG);
+ packageMonitorThread.start();
+ mPackageMonitor.register(context, packageMonitorThread.getLooper(), true);
final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(ACTION_USER_ADDED);
@@ -372,166 +365,171 @@
return defaultPackages.toArray(new String[defaultPackages.size()]);
}
- private final class PackageReceiver extends BroadcastReceiver {
+ private final class OverlayManagerPackageMonitor extends PackageMonitor {
+
@Override
- public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
- final String action = intent.getAction();
- if (action == null) {
- Slog.e(TAG, "Cannot handle package broadcast with null action");
- return;
- }
- final Uri data = intent.getData();
- if (data == null) {
- Slog.e(TAG, "Cannot handle package broadcast with null data");
- return;
- }
- final String packageName = data.getSchemeSpecificPart();
-
- final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
- final boolean systemUpdateUninstall =
- intent.getBooleanExtra(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, false);
-
- final int[] userIds;
- final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
- if (extraUid == UserHandle.USER_NULL) {
- userIds = mUserManager.getUserIds();
- } else {
- userIds = new int[] { UserHandle.getUserId(extraUid) };
- }
-
- switch (action) {
- case ACTION_PACKAGE_ADDED:
- if (replacing) {
- onPackageReplaced(packageName, userIds);
- } else {
- onPackageAdded(packageName, userIds);
- }
- break;
- case ACTION_PACKAGE_CHANGED:
- // ignore the intent if it was sent by the package manager as a result of the
- // overlay manager having sent ACTION_OVERLAY_CHANGED
- if (!ACTION_OVERLAY_CHANGED.equals(intent.getStringExtra(EXTRA_REASON))) {
- onPackageChanged(packageName, userIds);
- }
- break;
- case ACTION_PACKAGE_REMOVED:
- if (replacing) {
- onPackageReplacing(packageName, systemUpdateUninstall, userIds);
- } else {
- onPackageRemoved(packageName, userIds);
- }
- break;
- default:
- // do nothing
- break;
- }
+ public void onPackageAppearedWithExtras(String packageName, Bundle extras) {
+ handlePackageAdd(packageName, extras);
}
- private void onPackageAdded(@NonNull final String packageName,
- @NonNull final int[] userIds) {
- try {
- traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
- for (final int userId : userIds) {
- synchronized (mLock) {
- var packageState = mPackageManager.onPackageAdded(packageName, userId);
- if (packageState != null && !mPackageManager.isInstantApp(packageName,
- userId)) {
- try {
- updateTargetPackagesLocked(
- mImpl.onPackageAdded(packageName, userId));
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageAdded internal error", e);
- }
+ @Override
+ public void onPackageChangedWithExtras(String packageName, Bundle extras) {
+ handlePackageChange(packageName, extras);
+ }
+
+ @Override
+ public void onPackageDisappearedWithExtras(String packageName, Bundle extras) {
+ handlePackageRemove(packageName, extras);
+ }
+ }
+
+ private int[] getUserIds(int uid) {
+ final int[] userIds;
+ if (uid == INVALID_UID) {
+ userIds = mUserManager.getUserIds();
+ } else {
+ userIds = new int[] { UserHandle.getUserId(uid) };
+ }
+ return userIds;
+ }
+
+ private void handlePackageAdd(String packageName, Bundle extras) {
+ final boolean replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+ final int uid = extras.getInt(Intent.EXTRA_UID, 0);
+ final int[] userIds = getUserIds(uid);
+ if (replacing) {
+ onPackageReplaced(packageName, userIds);
+ } else {
+ onPackageAdded(packageName, userIds);
+ }
+ }
+
+ private void handlePackageChange(String packageName, Bundle extras) {
+ final int uid = extras.getInt(Intent.EXTRA_UID, 0);
+ final int[] userIds = getUserIds(uid);
+ if (!ACTION_OVERLAY_CHANGED.equals(extras.getString(EXTRA_REASON))) {
+ onPackageChanged(packageName, userIds);
+ }
+ }
+
+ private void handlePackageRemove(String packageName, Bundle extras) {
+ final boolean replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+ final boolean systemUpdateUninstall =
+ extras.getBoolean(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, false);
+ final int uid = extras.getInt(Intent.EXTRA_UID, 0);
+ final int[] userIds = getUserIds(uid);
+
+ if (replacing) {
+ onPackageReplacing(packageName, systemUpdateUninstall, userIds);
+ } else {
+ onPackageRemoved(packageName, userIds);
+ }
+ }
+
+ private void onPackageAdded(@NonNull final String packageName,
+ @NonNull final int[] userIds) {
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
+ for (final int userId : userIds) {
+ synchronized (mLock) {
+ var packageState = mPackageManager.onPackageAdded(packageName, userId);
+ if (packageState != null && !mPackageManager.isInstantApp(packageName,
+ userId)) {
+ try {
+ updateTargetPackagesLocked(
+ mImpl.onPackageAdded(packageName, userId));
+ } catch (OperationFailedException e) {
+ Slog.e(TAG, "onPackageAdded internal error", e);
}
}
}
- } finally {
- traceEnd(TRACE_TAG_RRO);
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
+ }
- private void onPackageChanged(@NonNull final String packageName,
- @NonNull final int[] userIds) {
- try {
- traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
- for (int userId : userIds) {
- synchronized (mLock) {
- var packageState = mPackageManager.onPackageUpdated(packageName, userId);
- if (packageState != null && !mPackageManager.isInstantApp(packageName,
- userId)) {
- try {
- updateTargetPackagesLocked(
- mImpl.onPackageChanged(packageName, userId));
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageChanged internal error", e);
- }
+ private void onPackageChanged(@NonNull final String packageName,
+ @NonNull final int[] userIds) {
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ var packageState = mPackageManager.onPackageUpdated(packageName, userId);
+ if (packageState != null && !mPackageManager.isInstantApp(packageName,
+ userId)) {
+ try {
+ updateTargetPackagesLocked(
+ mImpl.onPackageChanged(packageName, userId));
+ } catch (OperationFailedException e) {
+ Slog.e(TAG, "onPackageChanged internal error", e);
}
}
}
- } finally {
- traceEnd(TRACE_TAG_RRO);
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
+ }
- private void onPackageReplacing(@NonNull final String packageName,
- boolean systemUpdateUninstall, @NonNull final int[] userIds) {
- try {
- traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
- for (int userId : userIds) {
- synchronized (mLock) {
- var packageState = mPackageManager.onPackageUpdated(packageName, userId);
- if (packageState != null && !mPackageManager.isInstantApp(packageName,
- userId)) {
- try {
- updateTargetPackagesLocked(mImpl.onPackageReplacing(packageName,
- systemUpdateUninstall, userId));
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageReplacing internal error", e);
- }
+ private void onPackageReplacing(@NonNull final String packageName,
+ boolean systemUpdateUninstall, @NonNull final int[] userIds) {
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ var packageState = mPackageManager.onPackageUpdated(packageName, userId);
+ if (packageState != null && !mPackageManager.isInstantApp(packageName,
+ userId)) {
+ try {
+ updateTargetPackagesLocked(mImpl.onPackageReplacing(packageName,
+ systemUpdateUninstall, userId));
+ } catch (OperationFailedException e) {
+ Slog.e(TAG, "onPackageReplacing internal error", e);
}
}
}
- } finally {
- traceEnd(TRACE_TAG_RRO);
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
+ }
- private void onPackageReplaced(@NonNull final String packageName,
- @NonNull final int[] userIds) {
- try {
- traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
- for (int userId : userIds) {
- synchronized (mLock) {
- var packageState = mPackageManager.onPackageUpdated(packageName, userId);
- if (packageState != null && !mPackageManager.isInstantApp(packageName,
- userId)) {
- try {
- updateTargetPackagesLocked(
- mImpl.onPackageReplaced(packageName, userId));
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageReplaced internal error", e);
- }
+ private void onPackageReplaced(@NonNull final String packageName,
+ @NonNull final int[] userIds) {
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ var packageState = mPackageManager.onPackageUpdated(packageName, userId);
+ if (packageState != null && !mPackageManager.isInstantApp(packageName,
+ userId)) {
+ try {
+ updateTargetPackagesLocked(
+ mImpl.onPackageReplaced(packageName, userId));
+ } catch (OperationFailedException e) {
+ Slog.e(TAG, "onPackageReplaced internal error", e);
}
}
}
- } finally {
- traceEnd(TRACE_TAG_RRO);
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
+ }
- private void onPackageRemoved(@NonNull final String packageName,
- @NonNull final int[] userIds) {
- try {
- traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
- for (int userId : userIds) {
- synchronized (mLock) {
- mPackageManager.onPackageRemoved(packageName, userId);
- updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
- }
+ private void onPackageRemoved(@NonNull final String packageName,
+ @NonNull final int[] userIds) {
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ mPackageManager.onPackageRemoved(packageName, userId);
+ updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
}
- } finally {
- traceEnd(TRACE_TAG_RRO);
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
@@ -684,7 +682,7 @@
synchronized (mLock) {
try {
mImpl.setEnabledExclusive(
- overlay, false /* withinCategory */, realUserId)
+ overlay, false /* withinCategory */, realUserId)
.ifPresent(
OverlayManagerService.this::updateTargetPackagesLocked);
return true;
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index 9a69d77..e367609 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -17,9 +17,14 @@
package com.android.server.pm;
import static android.os.PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED;
+import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.Process.SYSTEM_UID;
import static android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED;
+
+import static com.android.server.pm.PackageManagerService.DEBUG_BACKUP;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
+import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
import static com.android.server.pm.PackageManagerService.PACKAGE_SCHEME;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.TAG;
@@ -28,6 +33,7 @@
import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.BroadcastOptions;
@@ -38,12 +44,18 @@
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.PowerExemptionManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.provider.DeviceConfig;
+import android.stats.storage.StorageEnums;
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
@@ -51,10 +63,15 @@
import android.util.SparseArray;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateInternal;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.function.BiFunction;
-import java.util.function.Supplier;
/**
* Helper class to send broadcasts for various situations.
@@ -70,14 +87,20 @@
private final UserManagerInternal mUmInternal;
private final ActivityManagerInternal mAmInternal;
private final Context mContext;
+ private final Handler mHandler;
+ private final PackageMonitorCallbackHelper mPackageMonitorCallbackHelper;
+ private final AppsFilterSnapshot mAppsFilter;
BroadcastHelper(PackageManagerServiceInjector injector) {
mUmInternal = injector.getUserManagerInternal();
mAmInternal = injector.getActivityManagerInternal();
mContext = injector.getContext();
+ mHandler = injector.getHandler();
+ mPackageMonitorCallbackHelper = injector.getPackageMonitorCallbackHelper();
+ mAppsFilter = injector.getAppsFilter();
}
- public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
+ void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
final int[] userIds, int[] instantUserIds,
@Nullable SparseArray<int[]> broadcastAllowList,
@@ -114,9 +137,16 @@
* the system and applications allowed to see instant applications to receive package
* lifecycle events for instant applications.
*/
- public void doSendBroadcast(String action, String pkg, Bundle extras,
- int flags, String targetPkg, IIntentReceiver finishedReceiver,
- int[] userIds, boolean isInstantApp, @Nullable SparseArray<int[]> broadcastAllowList,
+ private void doSendBroadcast(
+ @NonNull String action,
+ @Nullable String pkg,
+ @Nullable Bundle extras,
+ int flags,
+ @Nullable String targetPkg,
+ @Nullable IIntentReceiver finishedReceiver,
+ @NonNull int[] userIds,
+ boolean isInstantApp,
+ @Nullable SparseArray<int[]> broadcastAllowList,
@Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
@Nullable Bundle bOptions) {
for (int userId : userIds) {
@@ -166,9 +196,11 @@
}
}
- public void sendResourcesChangedBroadcast(@NonNull Supplier<Computer> snapshotComputer,
- boolean mediaStatus, boolean replacing, @NonNull String[] pkgNames,
- @NonNull int[] uids) {
+ void sendResourcesChangedBroadcast(@NonNull Computer snapshot,
+ boolean mediaStatus,
+ boolean replacing,
+ @NonNull String[] pkgNames,
+ @NonNull int[] uids) {
if (ArrayUtils.isEmpty(pkgNames) || ArrayUtils.isEmpty(uids)) {
return;
}
@@ -184,7 +216,7 @@
null /* targetPkg */, null /* finishedReceiver */, null /* userIds */,
null /* instantUserIds */, null /* broadcastAllowList */,
(callingUid, intentExtras) -> filterExtrasChangedPackageList(
- snapshotComputer.get(), callingUid, intentExtras),
+ snapshot, callingUid, intentExtras),
null /* bOptions */);
}
@@ -193,8 +225,9 @@
* automatically without needing an explicit launch.
* Send it a LOCKED_BOOT_COMPLETED/BOOT_COMPLETED if it would ordinarily have gotten ones.
*/
- public void sendBootCompletedBroadcastToSystemApp(
- String packageName, boolean includeStopped, int userId) {
+ private void sendBootCompletedBroadcastToSystemApp(@NonNull String packageName,
+ boolean includeStopped,
+ int userId) {
// If user is not running, the app didn't miss any broadcast
if (!mUmInternal.isUserRunning(userId)) {
return;
@@ -229,7 +262,7 @@
}
}
- public @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
+ private @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
@PowerExemptionManager.ReasonCode int reasonCode) {
long duration = 10_000;
if (mAmInternal != null) {
@@ -242,9 +275,14 @@
return bOptions;
}
- public void sendPackageChangedBroadcast(String packageName, boolean dontKillApp,
- ArrayList<String> componentNames, int packageUid, String reason,
- int[] userIds, int[] instantUserIds, SparseArray<int[]> broadcastAllowList) {
+ private void sendPackageChangedBroadcast(@NonNull String packageName,
+ boolean dontKillApp,
+ @NonNull ArrayList<String> componentNames,
+ int packageUid,
+ @Nullable String reason,
+ @Nullable int[] userIds,
+ @Nullable int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastAllowList) {
if (DEBUG_INSTALL) {
Log.v(TAG, "Sending package changed: package=" + packageName + " components="
+ componentNames);
@@ -269,7 +307,7 @@
null /* bOptions */);
}
- public static void sendDeviceCustomizationReadyBroadcast() {
+ static void sendDeviceCustomizationReadyBroadcast() {
final Intent intent = new Intent(Intent.ACTION_DEVICE_CUSTOMIZATION_READY);
intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
final IActivityManager am = ActivityManager.getService();
@@ -285,15 +323,23 @@
}
}
- public void sendSessionCommitBroadcast(PackageInstaller.SessionInfo sessionInfo, int userId,
- int launcherUid, @Nullable ComponentName launcherComponent,
- @Nullable String appPredictionServicePackage) {
+ void sendSessionCommitBroadcast(@NonNull Computer snapshot,
+ @NonNull PackageInstaller.SessionInfo sessionInfo,
+ int userId,
+ @Nullable String appPredictionServicePackage) {
+ UserManagerService ums = UserManagerService.getInstance();
+ if (ums == null || sessionInfo.isStaged()) {
+ return;
+ }
+ final UserInfo parent = ums.getProfileParent(userId);
+ final int launcherUserId = (parent != null) ? parent.id : userId;
+ final ComponentName launcherComponent = snapshot.getDefaultHomeActivity(launcherUserId);
if (launcherComponent != null) {
Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
.putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
.putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
.setPackage(launcherComponent.getPackageName());
- mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
+ mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUserId));
}
// TODO(b/122900055) Change/Remove this and replace with new permission role.
if (appPredictionServicePackage != null) {
@@ -301,30 +347,278 @@
.putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
.putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
.setPackage(appPredictionServicePackage);
- mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUid));
+ mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUserId));
}
}
- public void sendPreferredActivityChangedBroadcast(int userId) {
- final IActivityManager am = ActivityManager.getService();
- if (am == null) {
+ void sendPreferredActivityChangedBroadcast(int userId) {
+ mHandler.post(() -> {
+ final IActivityManager am = ActivityManager.getService();
+ if (am == null) {
+ return;
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ try {
+ am.broadcastIntentWithFeature(null, null, intent, null, null,
+ 0, null, null, null, null, null, android.app.AppOpsManager.OP_NONE,
+ null, false, false, userId);
+ } catch (RemoteException e) {
+ }
+ });
+ }
+
+ void sendPostInstallBroadcasts(@NonNull Computer snapshot,
+ @NonNull InstallRequest request,
+ @NonNull String packageName,
+ @NonNull String requiredPermissionControllerPackage,
+ @NonNull String[] requiredVerifierPackages,
+ @NonNull String requiredInstallerPackage,
+ @NonNull PackageSender packageSender,
+ boolean isLaunchedForRestore,
+ boolean isKillApp,
+ boolean isUpdate,
+ boolean isArchived) {
+ // Send the removed broadcasts
+ if (request.getRemovedInfo() != null) {
+ if (request.getRemovedInfo().mIsExternal) {
+ if (DEBUG_INSTALL) {
+ Slog.i(TAG, "upgrading pkg " + request.getRemovedInfo().mRemovedPackage
+ + " is ASEC-hosted -> UNAVAILABLE");
+ }
+ final String[] pkgNames = new String[]{
+ request.getRemovedInfo().mRemovedPackage};
+ final int[] uids = new int[]{request.getRemovedInfo().mUid};
+ notifyResourcesChanged(
+ false /* mediaStatus */, true /* replacing */, pkgNames, uids);
+ sendResourcesChangedBroadcast(
+ snapshot, false /* mediaStatus */, true /* replacing */, pkgNames, uids);
+ }
+ sendPackageRemovedBroadcasts(
+ request.getRemovedInfo(), packageSender, isKillApp, false /*removedBySystem*/,
+ false /*isArchived*/);
+ }
+
+ final int[] firstUserIds = request.getFirstTimeBroadcastUserIds();
+ final int[] firstInstantUserIds = request.getFirstTimeBroadcastInstantUserIds();
+ final int[] updateUserIds = request.getUpdateBroadcastUserIds();
+ final int[] instantUserIds = request.getUpdateBroadcastInstantUserIds();
+
+ final String installerPackageName =
+ request.getInstallerPackageName() != null
+ ? request.getInstallerPackageName()
+ : request.getRemovedInfo() != null
+ ? request.getRemovedInfo().mInstallerPackageName
+ : null;
+
+ Bundle extras = new Bundle();
+ extras.putInt(Intent.EXTRA_UID, request.getAppId());
+ if (isUpdate) {
+ extras.putBoolean(Intent.EXTRA_REPLACING, true);
+ }
+ if (isArchived) {
+ extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
+ }
+ extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, request.getDataLoaderType());
+
+ final String staticSharedLibraryName = request.getPkg().getStaticSharedLibraryName();
+ // If a package is a static shared library, then only the installer of the package
+ // should get the broadcast.
+ if (installerPackageName != null && staticSharedLibraryName != null) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, 0 /*flags*/,
+ installerPackageName, null /*finishedReceiver*/,
+ request.getNewUsers(), null /* instantUserIds*/,
+ null /* broadcastAllowList */, null);
+ }
+
+ // Send installed broadcasts if the package is not a static shared lib.
+ if (staticSharedLibraryName == null) {
+ // Send PACKAGE_ADDED broadcast for users that see the package for the first time
+ // sendPackageAddedForNewUsers also deals with system apps
+ final int appId = UserHandle.getAppId(request.getAppId());
+ final boolean isSystem = request.isInstallSystem();
+ final boolean isVirtualPreload =
+ ((request.getInstallFlags() & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
+ sendPackageAddedForNewUsers(snapshot, packageName,
+ isSystem || isVirtualPreload,
+ isVirtualPreload /*startReceiver*/, appId,
+ firstUserIds, firstInstantUserIds, isArchived, request.getDataLoaderType());
+
+ // Send PACKAGE_ADDED broadcast for users that don't see
+ // the package for the first time
+
+ // Send to all running apps.
+ final SparseArray<int[]> newBroadcastAllowList =
+ mAppsFilter.getVisibilityAllowList(snapshot,
+ snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
+ updateUserIds, snapshot.getPackageStates());
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, 0 /*flags*/,
+ null /*targetPackage*/, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds, newBroadcastAllowList, null);
+ // Send to the installer, even if it's not running.
+ if (installerPackageName != null) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, 0 /*flags*/,
+ installerPackageName, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
+ }
+ // Send to PermissionController for all update users, even if it may not be running
+ // for some users
+ if (isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, 0 /*flags*/,
+ requiredPermissionControllerPackage, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
+ }
+ // Notify required verifier(s) that are not the installer of record for the package.
+ for (String verifierPackageName : requiredVerifierPackages) {
+ if (verifierPackageName != null && !verifierPackageName.equals(
+ installerPackageName)) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED,
+ packageName,
+ extras, 0 /*flags*/,
+ verifierPackageName, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds, null /* broadcastAllowList */,
+ null);
+ }
+ }
+ // If package installer is defined, notify package installer about new
+ // app installed
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
+ requiredInstallerPackage, null /*finishedReceiver*/,
+ firstUserIds, instantUserIds, null /* broadcastAllowList */, null);
+
+ // Send replaced for users that don't see the package for the first time
+ if (isUpdate) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED,
+ packageName, extras, 0 /*flags*/,
+ null /*targetPackage*/, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds,
+ request.getRemovedInfo().mBroadcastAllowList, null);
+ if (installerPackageName != null) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED, packageName,
+ extras, 0 /*flags*/,
+ installerPackageName, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds, null /*broadcastAllowList*/,
+ null);
+ }
+ for (String verifierPackageName : requiredVerifierPackages) {
+ if (verifierPackageName != null && !verifierPackageName.equals(
+ installerPackageName)) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED,
+ packageName, extras, 0 /*flags*/, verifierPackageName,
+ null /*finishedReceiver*/, updateUserIds, instantUserIds,
+ null /*broadcastAllowList*/, null);
+ }
+ }
+ sendPackageBroadcastAndNotify(Intent.ACTION_MY_PACKAGE_REPLACED,
+ null /*package*/, null /*extras*/, 0 /*flags*/,
+ packageName /*targetPackage*/,
+ null /*finishedReceiver*/, updateUserIds, instantUserIds,
+ null /*broadcastAllowList*/,
+ getTemporaryAppAllowlistBroadcastOptions(
+ REASON_PACKAGE_REPLACED).toBundle());
+ } else if (isLaunchedForRestore && !request.isInstallSystem()) {
+ // First-install and we did a restore, so we're responsible for the
+ // first-launch broadcast.
+ if (DEBUG_BACKUP) {
+ Slog.i(TAG, "Post-restore of " + packageName
+ + " sending FIRST_LAUNCH in " + Arrays.toString(firstUserIds));
+ }
+ sendFirstLaunchBroadcast(packageName, installerPackageName,
+ firstUserIds, firstInstantUserIds);
+ }
+
+ // Send broadcast package appeared if external for all users
+ if (request.getPkg().isExternalStorage()) {
+ if (!isUpdate) {
+ final StorageManager storage = mContext.getSystemService(StorageManager.class);
+ VolumeInfo volume =
+ storage.findVolumeByUuid(
+ StorageManager.convert(
+ request.getPkg().getVolumeUuid()).toString());
+ int packageExternalStorageType =
+ PackageManagerServiceUtils.getPackageExternalStorageType(volume,
+ /* isExternalStorage */ true);
+ // If the package was installed externally, log it.
+ if (packageExternalStorageType != StorageEnums.UNKNOWN) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
+ packageExternalStorageType, packageName);
+ }
+ }
+ if (DEBUG_INSTALL) {
+ Slog.i(TAG, "upgrading pkg " + packageName + " is external");
+ }
+ if (!isArchived) {
+ final String[] pkgNames = new String[]{packageName};
+ final int[] uids = new int[]{request.getPkg().getUid()};
+ sendResourcesChangedBroadcast(snapshot,
+ true /* mediaStatus */, true /* replacing */, pkgNames, uids);
+ notifyResourcesChanged(true /* mediaStatus */,
+ true /* replacing */, pkgNames, uids);
+ }
+ }
+ } else { // if static shared lib
+ final ArrayList<AndroidPackage> libraryConsumers = request.getLibraryConsumers();
+ if (!ArrayUtils.isEmpty(libraryConsumers)) {
+ // No need to kill consumers if it's installation of new version static shared lib.
+ final boolean dontKillApp = !isUpdate;
+ for (int i = 0; i < libraryConsumers.size(); i++) {
+ AndroidPackage pkg = libraryConsumers.get(i);
+ // send broadcast that all consumers of the static shared library have changed
+ sendPackageChangedBroadcast(snapshot, pkg.getPackageName(),
+ dontKillApp,
+ new ArrayList<>(Collections.singletonList(pkg.getPackageName())),
+ pkg.getUid(), null);
+ }
+ }
+ }
+ }
+
+ private void sendPackageAddedForNewUsers(@NonNull Computer snapshot,
+ @NonNull String packageName,
+ boolean sendBootCompleted,
+ boolean includeStopped,
+ @AppIdInt int appId,
+ int[] userIds,
+ int[] instantUserIds,
+ boolean isArchived,
+ int dataLoaderType) {
+ if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) {
return;
}
-
- final Intent intent = new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- try {
- am.broadcastIntentWithFeature(null, null, intent, null, null,
- 0, null, null, null, null, null, android.app.AppOpsManager.OP_NONE,
- null, false, false, userId);
- } catch (RemoteException e) {
+ SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList(snapshot,
+ snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
+ userIds, snapshot.getPackageStates());
+ mHandler.post(
+ () -> sendPackageAddedForNewUsers(packageName, appId, userIds,
+ instantUserIds, isArchived, dataLoaderType, broadcastAllowList));
+ mPackageMonitorCallbackHelper.notifyPackageAddedForNewUsers(packageName, appId, userIds,
+ instantUserIds, isArchived, dataLoaderType, broadcastAllowList, mHandler);
+ if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
+ mHandler.post(() -> {
+ for (int userId : userIds) {
+ sendBootCompletedBroadcastToSystemApp(
+ packageName, includeStopped, userId);
+ }
+ }
+ );
}
}
- public void sendPackageAddedForNewUsers(String packageName, @AppIdInt int appId, int[] userIds,
- int[] instantUserIds, boolean isArchived, int dataLoaderType,
- SparseArray<int[]> broadcastAllowlist) {
+ private void sendPackageAddedForNewUsers(@NonNull String packageName,
+ @AppIdInt int appId,
+ int[] userIds,
+ int[] instantUserIds,
+ boolean isArchived,
+ int dataLoaderType,
+ @NonNull SparseArray<int[]> broadcastAllowlist) {
Bundle extras = new Bundle(1);
// Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
final int uid = UserHandle.getUid(
@@ -349,7 +643,30 @@
}
}
- public void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
+ void sendPackageAddedForUser(@NonNull Computer snapshot,
+ @NonNull String packageName,
+ @NonNull PackageStateInternal packageState,
+ int userId,
+ boolean isArchived,
+ int dataLoaderType,
+ @Nullable String appPredictionServicePackage) {
+ final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
+ final boolean isSystem = packageState.isSystem();
+ final boolean isInstantApp = userState.isInstantApp();
+ final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
+ final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
+ sendPackageAddedForNewUsers(snapshot, packageName, isSystem /*sendBootCompleted*/,
+ false /*startReceiver*/, packageState.getAppId(), userIds, instantUserIds,
+ isArchived, dataLoaderType);
+
+ // Send a session commit broadcast
+ final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
+ info.installReason = userState.getInstallReason();
+ info.appPackageName = packageName;
+ sendSessionCommitBroadcast(snapshot, info, userId, appPredictionServicePackage);
+ }
+
+ void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
int[] userIds, int[] instantUserIds) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0,
installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */,
@@ -366,7 +683,7 @@
* access all the packages in the extras.
*/
@Nullable
- public static Bundle filterExtrasChangedPackageList(@NonNull Computer snapshot, int callingUid,
+ private static Bundle filterExtrasChangedPackageList(@NonNull Computer snapshot, int callingUid,
@NonNull Bundle extras) {
if (UserHandle.isCore(callingUid)) {
// see all
@@ -392,7 +709,7 @@
}
/** Returns whether the Safety Label Change notification, a privacy feature, is enabled. */
- public static boolean isPrivacySafetyLabelChangeNotificationsEnabled(Context context) {
+ private static boolean isPrivacySafetyLabelChangeNotificationsEnabled(Context context) {
PackageManager packageManager = context.getPackageManager();
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, true)
@@ -424,4 +741,323 @@
pkgList.size() > 0 ? pkgList.toArray(new String[pkgList.size()]) : null,
uidList != null && uidList.size() > 0 ? uidList.toArray() : null);
}
+
+ void sendApplicationHiddenForUser(@NonNull String packageName,
+ @NonNull PackageStateInternal packageState,
+ int userId,
+ @NonNull PackageSender packageSender) {
+ final PackageRemovedInfo info = new PackageRemovedInfo();
+ info.mRemovedPackage = packageName;
+ info.mInstallerPackageName = packageState.getInstallSource().mInstallerPackageName;
+ info.mRemovedUsers = new int[] {userId};
+ info.mBroadcastUsers = new int[] {userId};
+ info.mUid = UserHandle.getUid(userId, packageState.getAppId());
+ info.mRemovedPackageVersionCode = packageState.getVersionCode();
+ sendPackageRemovedBroadcasts(info, packageSender, true /*killApp*/,
+ false /*removedBySystem*/, false /*isArchived*/);
+ }
+
+ void sendPackageChangedBroadcast(@NonNull Computer snapshot,
+ @NonNull String packageName,
+ boolean dontKillApp,
+ @NonNull ArrayList<String> componentNames,
+ int packageUid,
+ @NonNull String reason) {
+ PackageStateInternal setting = snapshot.getPackageStateInternal(packageName,
+ Process.SYSTEM_UID);
+ if (setting == null) {
+ return;
+ }
+ final int userId = UserHandle.getUserId(packageUid);
+ final boolean isInstantApp =
+ snapshot.isInstantAppInternal(packageName, userId, Process.SYSTEM_UID);
+ final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
+ final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
+ final SparseArray<int[]> broadcastAllowList =
+ isInstantApp ? null : snapshot.getVisibilityAllowLists(packageName, userIds);
+ mHandler.post(() -> sendPackageChangedBroadcast(
+ packageName, dontKillApp, componentNames, packageUid, reason, userIds,
+ instantUserIds, broadcastAllowList));
+ mPackageMonitorCallbackHelper.notifyPackageChanged(packageName, dontKillApp, componentNames,
+ packageUid, reason, userIds, instantUserIds, broadcastAllowList, mHandler);
+ }
+
+ private void sendPackageBroadcastAndNotify(@NonNull String action,
+ @NonNull String pkg,
+ @NonNull Bundle extras,
+ int flags,
+ @Nullable String targetPkg,
+ @Nullable IIntentReceiver finishedReceiver,
+ @NonNull int[] userIds,
+ @NonNull int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastAllowList,
+ @Nullable Bundle bOptions) {
+ mHandler.post(() -> sendPackageBroadcast(action, pkg, extras, flags,
+ targetPkg, finishedReceiver, userIds, instantUserIds, broadcastAllowList,
+ null /* filterExtrasForReceiver */, bOptions));
+ if (targetPkg == null) {
+ // For some broadcast action, e.g. ACTION_PACKAGE_ADDED, this method will be called
+ // many times to different targets, e.g. installer app, permission controller, other
+ // registered apps. We should filter it to avoid calling back many times for the same
+ // action. When the targetPkg is set, it sends the broadcast to specific app, e.g.
+ // installer app or null for registered apps. The callback only need to send back to the
+ // registered apps so we check the null condition here.
+ notifyPackageMonitor(action, pkg, extras, userIds, instantUserIds, broadcastAllowList);
+ }
+ }
+
+ void sendSystemPackageUpdatedBroadcasts(@NonNull PackageRemovedInfo packageRemovedInfo) {
+ if (!packageRemovedInfo.mIsRemovedPackageSystemUpdate) {
+ return;
+ }
+
+ final String removedPackage = packageRemovedInfo.mRemovedPackage;
+ final int removedAppId = packageRemovedInfo.mRemovedAppId;
+ final int uid = packageRemovedInfo.mUid;
+ final String installerPackageName = packageRemovedInfo.mInstallerPackageName;
+ final SparseArray<int[]> broadcastAllowList = packageRemovedInfo.mBroadcastAllowList;
+
+ Bundle extras = new Bundle(2);
+ extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
+ extras.putBoolean(Intent.EXTRA_REPLACING, true);
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras,
+ 0, null /*targetPackage*/, null, null, null, broadcastAllowList, null);
+
+ if (installerPackageName != null) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED,
+ removedPackage, extras, 0 /*flags*/,
+ installerPackageName, null, null, null, null /* broadcastAllowList */,
+ null);
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED,
+ removedPackage, extras, 0 /*flags*/,
+ installerPackageName, null, null, null, null /* broadcastAllowList */,
+ null);
+ }
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
+ extras, 0, null /*targetPackage*/, null, null, null, broadcastAllowList, null);
+ sendPackageBroadcastAndNotify(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
+ removedPackage, null, null, null, null /* broadcastAllowList */,
+ getTemporaryBroadcastOptionsForSystemPackageUpdate(REASON_PACKAGE_REPLACED)
+ .toBundle());
+ }
+
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ private @NonNull BroadcastOptions getTemporaryBroadcastOptionsForSystemPackageUpdate(
+ @PowerExemptionManager.ReasonCode int reasonCode) {
+ long duration = 10_000;
+ if (mAmInternal != null) {
+ duration = mAmInternal.getBootTimeTempAllowListDuration();
+ }
+ final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
+ bOptions.setTemporaryAppAllowlist(duration,
+ TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ reasonCode, "");
+ return bOptions;
+ }
+
+
+ void sendPackageRemovedBroadcasts(
+ @NonNull PackageRemovedInfo packageRemovedInfo,
+ @NonNull PackageSender packageSender,
+ boolean killApp,
+ boolean removedBySystem,
+ boolean isArchived) {
+ final String removedPackage = packageRemovedInfo.mRemovedPackage;
+ final int removedAppId = packageRemovedInfo.mRemovedAppId;
+ final int uid = packageRemovedInfo.mUid;
+ final String installerPackageName = packageRemovedInfo.mInstallerPackageName;
+ final int[] broadcastUserIds = packageRemovedInfo.mBroadcastUsers;
+ final int[] instantUserIds = packageRemovedInfo.mInstantUserIds;
+ final SparseArray<int[]> broadcastAllowList = packageRemovedInfo.mBroadcastAllowList;
+ final boolean dataRemoved = packageRemovedInfo.mDataRemoved;
+ final boolean isUpdate = packageRemovedInfo.mIsUpdate;
+ final boolean isRemovedPackageSystemUpdate =
+ packageRemovedInfo.mIsRemovedPackageSystemUpdate;
+ final boolean isRemovedForAllUsers = packageRemovedInfo.mRemovedForAllUsers;
+ final boolean isStaticSharedLib = packageRemovedInfo.mIsStaticSharedLib;
+
+ Bundle extras = new Bundle();
+ final int removedUid = removedAppId >= 0 ? removedAppId : uid;
+ extras.putInt(Intent.EXTRA_UID, removedUid);
+ extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
+ extras.putBoolean(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, isRemovedPackageSystemUpdate);
+ extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
+ extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem);
+ final boolean isReplace = isUpdate || isRemovedPackageSystemUpdate;
+ if (isReplace || isArchived) {
+ extras.putBoolean(Intent.EXTRA_REPLACING, true);
+ }
+ if (isArchived) {
+ extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
+ }
+ extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, isRemovedForAllUsers);
+
+ // Send PACKAGE_REMOVED broadcast to the respective installer.
+ if (removedPackage != null && installerPackageName != null) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REMOVED,
+ removedPackage, extras, 0 /*flags*/,
+ installerPackageName, null, broadcastUserIds, instantUserIds, null, null);
+ }
+ if (isStaticSharedLib) {
+ // When uninstalling static shared libraries, only the package's installer needs to be
+ // sent a PACKAGE_REMOVED broadcast. There are no other intended recipients.
+ return;
+ }
+ if (removedPackage != null) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REMOVED,
+ removedPackage, extras, 0, null /*targetPackage*/, null,
+ broadcastUserIds, instantUserIds, broadcastAllowList, null);
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REMOVED_INTERNAL,
+ removedPackage, extras, 0 /*flags*/, PLATFORM_PACKAGE_NAME,
+ null /*finishedReceiver*/, broadcastUserIds, instantUserIds,
+ broadcastAllowList, null /*bOptions*/);
+ if (dataRemoved && !isRemovedPackageSystemUpdate) {
+ sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_FULLY_REMOVED,
+ removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
+ null, broadcastUserIds, instantUserIds, broadcastAllowList, null);
+ packageSender.notifyPackageRemoved(removedPackage, removedUid);
+ }
+ }
+ if (removedAppId >= 0) {
+ // If a system app's updates are uninstalled the UID is not actually removed. Some
+ // services need to know the package name affected.
+ if (isReplace) {
+ extras.putString(Intent.EXTRA_PACKAGE_NAME, removedPackage);
+ }
+
+ sendPackageBroadcastAndNotify(Intent.ACTION_UID_REMOVED,
+ null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+ null, null, broadcastUserIds, instantUserIds, broadcastAllowList, null);
+ }
+ }
+
+ /**
+ * Send broadcast intents for packages suspension changes.
+ *
+ * @param intent The action name of the suspension intent.
+ * @param pkgList The names of packages which have suspension changes.
+ * @param uidList The uids of packages which have suspension changes.
+ * @param userId The user where packages reside.
+ */
+ void sendPackagesSuspendedOrUnsuspendedForUser(@NonNull Computer snapshot,
+ @NonNull String intent,
+ @NonNull String[] pkgList,
+ @NonNull int[] uidList,
+ boolean quarantined,
+ int userId) {
+ final Bundle extras = new Bundle(3);
+ extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
+ extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
+ if (quarantined) {
+ extras.putBoolean(Intent.EXTRA_QUARANTINED, true);
+ }
+ final int flags = Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND;
+ final Bundle options = new BroadcastOptions()
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
+ .toBundle();
+ mHandler.post(() -> sendPackageBroadcast(intent, null /* pkg */,
+ extras, flags, null /* targetPkg */, null /* finishedReceiver */,
+ new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */,
+ (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
+ snapshot, callingUid, intentExtras),
+ options));
+ notifyPackageMonitor(intent, null /* pkg */, extras, new int[]{userId},
+ null /* instantUserIds */, null /* broadcastAllowList */);
+ }
+
+ void sendMyPackageSuspendedOrUnsuspended(@NonNull Computer snapshot,
+ @NonNull String[] affectedPackages,
+ boolean suspended,
+ int userId) {
+ final String action = suspended
+ ? Intent.ACTION_MY_PACKAGE_SUSPENDED
+ : Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
+ mHandler.post(() -> {
+ final IActivityManager am = ActivityManager.getService();
+ if (am == null) {
+ Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
+ + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
+ return;
+ }
+ final int[] targetUserIds = new int[] {userId};
+ for (String packageName : affectedPackages) {
+ final Bundle appExtras = suspended
+ ? SuspendPackageHelper.getSuspendedPackageAppExtras(
+ snapshot, packageName, userId, SYSTEM_UID)
+ : null;
+ final Bundle intentExtras;
+ if (appExtras != null) {
+ intentExtras = new Bundle(1);
+ intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
+ } else {
+ intentExtras = null;
+ }
+ doSendBroadcast(action, null, intentExtras,
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
+ targetUserIds, false, null, null, null);
+ }
+ });
+ }
+
+ /**
+ * Send broadcast intents for packages distracting changes.
+ *
+ * @param pkgList The names of packages which have suspension changes.
+ * @param uidList The uids of packages which have suspension changes.
+ * @param userId The user where packages reside.
+ */
+ void sendDistractingPackagesChanged(@NonNull Computer snapshot,
+ @NonNull String[] pkgList,
+ @NonNull int[] uidList,
+ int userId,
+ int distractionFlags) {
+ final Bundle extras = new Bundle();
+ extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
+ extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
+ extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags);
+
+ mHandler.post(() -> sendPackageBroadcast(
+ Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */,
+ extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */,
+ null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */,
+ null /* broadcastAllowList */,
+ (callingUid, intentExtras) -> filterExtrasChangedPackageList(
+ snapshot, callingUid, intentExtras),
+ null /* bOptions */));
+ }
+
+ void sendResourcesChangedBroadcastAndNotify(@NonNull Computer snapshot,
+ boolean mediaStatus,
+ boolean replacing,
+ @NonNull ArrayList<AndroidPackage> packages) {
+ final int size = packages.size();
+ final String[] packageNames = new String[size];
+ final int[] packageUids = new int[size];
+ for (int i = 0; i < size; i++) {
+ final AndroidPackage pkg = packages.get(i);
+ packageNames[i] = pkg.getPackageName();
+ packageUids[i] = pkg.getUid();
+ }
+ sendResourcesChangedBroadcast(snapshot, mediaStatus,
+ replacing, packageNames, packageUids);
+ notifyResourcesChanged(mediaStatus, replacing, packageNames, packageUids);
+ }
+
+ private void notifyPackageMonitor(@NonNull String action,
+ @NonNull String pkg,
+ @Nullable Bundle extras,
+ @NonNull int[] userIds,
+ @NonNull int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastAllowList) {
+ mPackageMonitorCallbackHelper.notifyPackageMonitor(action, pkg, extras, userIds,
+ instantUserIds, broadcastAllowList, mHandler);
+ }
+
+ private void notifyResourcesChanged(boolean mediaStatus,
+ boolean replacing,
+ @NonNull String[] pkgNames,
+ @NonNull int[] uids) {
+ mPackageMonitorCallbackHelper.notifyResourcesChanged(mediaStatus, replacing, pkgNames,
+ uids, mHandler);
+ }
}
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 83f90a1..8e767e7 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -63,7 +63,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.ArchiveState;
import com.android.server.pm.pkg.PackageStateInternal;
@@ -87,19 +86,16 @@
private final PackageManagerService mPm;
private final UserManagerInternal mUserManagerInternal;
- private final PermissionManagerServiceInternal mPermissionManager;
private final RemovePackageHelper mRemovePackageHelper;
+ private final BroadcastHelper mBroadcastHelper;
// TODO(b/198166813): remove PMS dependency
- DeletePackageHelper(PackageManagerService pm, RemovePackageHelper removePackageHelper) {
+ DeletePackageHelper(PackageManagerService pm, RemovePackageHelper removePackageHelper,
+ BroadcastHelper broadcastHelper) {
mPm = pm;
mUserManagerInternal = mPm.mInjector.getUserManagerInternal();
- mPermissionManager = mPm.mInjector.getPermissionManagerServiceInternal();
mRemovePackageHelper = removePackageHelper;
- }
-
- DeletePackageHelper(PackageManagerService pm) {
- this(pm, new RemovePackageHelper(pm));
+ mBroadcastHelper = broadcastHelper;
}
/**
@@ -121,7 +117,7 @@
*/
public int deletePackageX(String packageName, long versionCode, int userId, int deleteFlags,
boolean removedBySystem) {
- final PackageRemovedInfo info = new PackageRemovedInfo(mPm);
+ final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;
final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
@@ -251,8 +247,9 @@
if (res) {
final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
final boolean isArchived = (deleteFlags & PackageManager.DELETE_ARCHIVE) != 0;
- info.sendPackageRemovedBroadcasts(killApp, removedBySystem, isArchived);
- info.sendSystemPackageUpdatedBroadcasts();
+ mBroadcastHelper.sendPackageRemovedBroadcasts(info, mPm, killApp,
+ removedBySystem, isArchived);
+ mBroadcastHelper.sendSystemPackageUpdatedBroadcasts(info);
PackageMetrics.onUninstallSucceeded(info, deleteFlags, removeUser);
}
@@ -314,7 +311,7 @@
Slog.i(TAG, "Enabling system stub after removal; pkg: "
+ stubPkg.getPackageName());
}
- new InstallPackageHelper(mPm).enableCompressedPackage(stubPkg, stubPs);
+ mPm.enableCompressedPackage(stubPkg, stubPs);
} else if (DEBUG_COMPRESSION) {
Slog.i(TAG, "System stub disabled for all users, leaving uncompressed "
+ "after removal; pkg: " + stubPkg.getPackageName());
@@ -491,8 +488,7 @@
// When an updated system application is deleted we delete the existing resources
// as well and fall back to existing code in system partition
deleteInstalledSystemPackage(action, allUserHandles, writeSettings);
- new InstallPackageHelper(mPm).restoreDisabledSystemPackageLIF(
- action, allUserHandles, writeSettings);
+ mPm.restoreDisabledSystemPackageLIF(action, allUserHandles, writeSettings);
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.getPackageName());
if (ps.isIncremental()) {
diff --git a/services/core/java/com/android/server/pm/DistractingPackageHelper.java b/services/core/java/com/android/server/pm/DistractingPackageHelper.java
index 8ebb6ea..c5ec73b 100644
--- a/services/core/java/com/android/server/pm/DistractingPackageHelper.java
+++ b/services/core/java/com/android/server/pm/DistractingPackageHelper.java
@@ -19,10 +19,7 @@
import static android.content.pm.PackageManager.RESTRICTION_NONE;
import android.annotation.NonNull;
-import android.content.Intent;
import android.content.pm.PackageManager.DistractionRestriction;
-import android.os.Bundle;
-import android.os.Handler;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IntArray;
@@ -42,17 +39,16 @@
// TODO(b/198166813): remove PMS dependency
private final PackageManagerService mPm;
- private final PackageManagerServiceInjector mInjector;
private final BroadcastHelper mBroadcastHelper;
private final SuspendPackageHelper mSuspendPackageHelper;
/**
* Constructor for {@link PackageManagerService}.
*/
- DistractingPackageHelper(PackageManagerService pm, PackageManagerServiceInjector injector,
- BroadcastHelper broadcastHelper, SuspendPackageHelper suspendPackageHelper) {
+ DistractingPackageHelper(PackageManagerService pm,
+ BroadcastHelper broadcastHelper,
+ SuspendPackageHelper suspendPackageHelper) {
mPm = pm;
- mInjector = injector;
mBroadcastHelper = broadcastHelper;
mSuspendPackageHelper = suspendPackageHelper;
}
@@ -127,8 +123,8 @@
if (!changedPackagesList.isEmpty()) {
final String[] changedPackages = changedPackagesList.toArray(
new String[changedPackagesList.size()]);
- sendDistractingPackagesChanged(changedPackages, changedUids.toArray(), userId,
- restrictionFlags);
+ mBroadcastHelper.sendDistractingPackagesChanged(mPm.snapshotComputer(),
+ changedPackages, changedUids.toArray(), userId, restrictionFlags);
mPm.scheduleWritePackageRestrictions(userId);
}
return unactionedPackages.toArray(new String[0]);
@@ -202,34 +198,9 @@
if (!changedPackages.isEmpty()) {
final String[] packageArray = changedPackages.toArray(
new String[changedPackages.size()]);
- sendDistractingPackagesChanged(packageArray, changedUids.toArray(), userId,
- RESTRICTION_NONE);
+ mBroadcastHelper.sendDistractingPackagesChanged(mPm.snapshotComputer(),
+ packageArray, changedUids.toArray(), userId, RESTRICTION_NONE);
mPm.scheduleWritePackageRestrictions(userId);
}
}
-
- /**
- * Send broadcast intents for packages distracting changes.
- *
- * @param pkgList The names of packages which have suspension changes.
- * @param uidList The uids of packages which have suspension changes.
- * @param userId The user where packages reside.
- */
- void sendDistractingPackagesChanged(@NonNull String[] pkgList, int[] uidList, int userId,
- int distractionFlags) {
- final Bundle extras = new Bundle();
- extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
- extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
- extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags);
-
- final Handler handler = mInjector.getHandler();
- handler.post(() -> mBroadcastHelper.sendPackageBroadcast(
- Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */,
- extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */,
- null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */,
- null /* broadcastAllowList */,
- (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
- mPm.snapshotComputer(), callingUid, intentExtras),
- null /* bOptions */));
- }
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index e1e5e6d..86cdc04 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -38,7 +38,6 @@
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
-import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.incremental.IncrementalManager.isIncrementalPath;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
@@ -50,7 +49,6 @@
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME;
-import static com.android.server.pm.PackageManagerService.DEBUG_BACKUP;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
@@ -130,7 +128,6 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Message;
@@ -143,9 +140,6 @@
import android.os.UserManager;
import android.os.incremental.IncrementalManager;
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.text.TextUtils;
@@ -163,7 +157,6 @@
import com.android.internal.security.VerityUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemConfig;
@@ -220,6 +213,7 @@
private final AppDataHelper mAppDataHelper;
private final BroadcastHelper mBroadcastHelper;
private final RemovePackageHelper mRemovePackageHelper;
+ private final DeletePackageHelper mDeletePackageHelper;
private final IncrementalManager mIncrementalManager;
private final ApexManager mApexManager;
private final DexManager mDexManager;
@@ -233,12 +227,17 @@
private final UpdateOwnershipHelper mUpdateOwnershipHelper;
// TODO(b/198166813): remove PMS dependency
- InstallPackageHelper(PackageManagerService pm, AppDataHelper appDataHelper) {
+ InstallPackageHelper(PackageManagerService pm,
+ AppDataHelper appDataHelper,
+ RemovePackageHelper removePackageHelper,
+ DeletePackageHelper deletePackageHelper,
+ BroadcastHelper broadcastHelper) {
mPm = pm;
mInjector = pm.mInjector;
mAppDataHelper = appDataHelper;
- mBroadcastHelper = new BroadcastHelper(pm.mInjector);
- mRemovePackageHelper = new RemovePackageHelper(pm);
+ mBroadcastHelper = broadcastHelper;
+ mRemovePackageHelper = removePackageHelper;
+ mDeletePackageHelper = deletePackageHelper;
mIncrementalManager = pm.mInjector.getIncrementalManager();
mApexManager = pm.mInjector.getApexManager();
mDexManager = pm.mInjector.getDexManager();
@@ -251,10 +250,6 @@
mUpdateOwnershipHelper = pm.mInjector.getUpdateOwnershipHelper();
}
- InstallPackageHelper(PackageManagerService pm) {
- this(pm, new AppDataHelper(pm));
- }
-
/**
* Commits the package scan and modifies system state.
* <p><em>WARNING:</em> The method may throw an exception in the middle
@@ -263,7 +258,7 @@
* possible and the system is not left in an inconsistent state.
*/
@GuardedBy("mPm.mLock")
- public AndroidPackage commitReconciledScanResultLocked(
+ private AndroidPackage commitReconciledScanResultLocked(
@NonNull ReconciledPackage reconciledPkg, int[] allUsers) {
final InstallRequest request = reconciledPkg.mInstallRequest;
// TODO(b/135203078): Move this even further away
@@ -731,8 +726,9 @@
}
// TODO(b/278553670) Store archive state for the user.
boolean isArchived = (pkgSetting.getPkg() == null);
- mPm.sendPackageAddedForUser(mPm.snapshotComputer(), packageName, pkgSetting, userId,
- isArchived, DataLoaderType.NONE);
+ mBroadcastHelper.sendPackageAddedForUser(mPm.snapshotComputer(), packageName,
+ pkgSetting, userId, isArchived, DataLoaderType.NONE,
+ mPm.mAppPredictionServicePackage);
synchronized (mPm.mLock) {
mPm.updateSequenceNumberLP(pkgSetting, new int[]{ userId });
}
@@ -1745,7 +1741,7 @@
}
// Update what is removed
- PackageRemovedInfo removedInfo = new PackageRemovedInfo(mPm);
+ PackageRemovedInfo removedInfo = new PackageRemovedInfo();
removedInfo.mUid = ps.getAppId();
removedInfo.mRemovedPackage = ps.getPackageName();
removedInfo.mInstallerPackageName =
@@ -2074,8 +2070,6 @@
final InstallRequest installRequest = reconciledPkg.mInstallRequest;
final ParsedPackage parsedPackage = installRequest.getParsedPackage();
final String packageName = parsedPackage.getPackageName();
- final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
- final DeletePackageHelper deletePackageHelper = new DeletePackageHelper(mPm);
installRequest.onCommitStarted();
if (installRequest.isInstallReplace()) {
@@ -2097,7 +2091,7 @@
allUsers, mPm.mSettings.getPackagesLocked());
if (installRequest.isInstallSystem()) {
// Remove existing system package
- removePackageHelper.removePackage(oldPackage, true);
+ mRemovePackageHelper.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
@@ -2113,7 +2107,7 @@
} else {
try {
// Settings will be written during the call to updateSettingsLI().
- deletePackageHelper.executeDeletePackage(
+ mDeletePackageHelper.executeDeletePackage(
reconciledPkg.mDeletePackageAction, packageName,
true, allUsers, false);
} catch (SystemDeleteException e) {
@@ -2796,24 +2790,21 @@
final Computer snapshot = mPm.snapshotComputer();
// Send broadcasts
for (int i = 0; i < numBroadcasts; i++) {
- mPm.sendPackageChangedBroadcast(snapshot, packages[i], true /* dontKillApp */,
- components[i], uids[i], null /* reason */);
+ mBroadcastHelper.sendPackageChangedBroadcast(snapshot, packages[i],
+ true /* dontKillApp */, components[i], uids[i], null /* reason */);
}
}
void handlePackagePostInstall(InstallRequest request, boolean launchedForRestore) {
final boolean killApp =
(request.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) == 0;
- final boolean virtualPreload =
- ((request.getInstallFlags() & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
- final String installerPackage = request.getInstallerPackageName();
- final int dataLoaderType = request.getDataLoaderType();
final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED;
final boolean update = request.isUpdate();
final boolean archived = request.isArchived();
final String packageName = request.getName();
+ final Computer snapshot = mPm.snapshotComputer();
final PackageStateInternal pkgSetting =
- succeeded ? mPm.snapshotComputer().getPackageStateInternal(packageName) : null;
+ succeeded ? snapshot.getPackageStateInternal(packageName) : null;
final boolean removedBeforeUpdate = (pkgSetting == null)
|| (pkgSetting.isSystem() && !pkgSetting.getPath().getPath().equals(
request.getPkg().getPath()));
@@ -2834,208 +2825,22 @@
// Clear the uid cache after we installed a new package.
mPm.mPerUidReadTimeoutsCache = null;
- // Send the removed broadcasts
- if (request.getRemovedInfo() != null) {
- if (request.getRemovedInfo().mIsExternal) {
- if (DEBUG_INSTALL) {
- Slog.i(TAG, "upgrading pkg " + request.getRemovedInfo().mRemovedPackage
- + " is ASEC-hosted -> UNAVAILABLE");
- }
- final String[] pkgNames = new String[]{
- request.getRemovedInfo().mRemovedPackage};
- final int[] uids = new int[]{request.getRemovedInfo().mUid};
- mPm.notifyResourcesChanged(false /* mediaStatus */,
- true /* replacing */, pkgNames, uids);
- mBroadcastHelper.sendResourcesChangedBroadcast(mPm::snapshotComputer,
- false /* mediaStatus */, true /* replacing */, pkgNames, uids);
- }
- request.getRemovedInfo().sendPackageRemovedBroadcasts(
- killApp, false /*removedBySystem*/, false /*isArchived*/);
- }
-
- final String installerPackageName =
- request.getInstallerPackageName() != null
- ? request.getInstallerPackageName()
- : request.getRemovedInfo() != null
- ? request.getRemovedInfo().mInstallerPackageName
- : null;
-
mPm.notifyInstantAppPackageInstalled(request.getPkg().getPackageName(),
request.getNewUsers());
request.populateBroadcastUsers();
final int[] firstUserIds = request.getFirstTimeBroadcastUserIds();
- final int[] firstInstantUserIds = request.getFirstTimeBroadcastInstantUserIds();
- final int[] updateUserIds = request.getUpdateBroadcastUserIds();
- final int[] instantUserIds = request.getUpdateBroadcastInstantUserIds();
- Bundle extras = new Bundle();
- extras.putInt(Intent.EXTRA_UID, request.getAppId());
- if (update) {
- extras.putBoolean(Intent.EXTRA_REPLACING, true);
- }
- if (archived) {
- extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
- }
- extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
-
- // If a package is a static shared library, then only the installer of the package
- // should get the broadcast.
- if (installerPackageName != null
- && request.getPkg().getStaticSharedLibraryName() != null) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, 0 /*flags*/,
- installerPackageName, null /*finishedReceiver*/,
- request.getNewUsers(), null /* instantUserIds*/,
- null /* broadcastAllowList */, null);
- }
-
- // Send installed broadcasts if the package is not a static shared lib.
if (request.getPkg().getStaticSharedLibraryName() == null) {
mPm.mProcessLoggingHandler.invalidateBaseApkHash(request.getPkg().getBaseApkPath());
-
- // Send PACKAGE_ADDED broadcast for users that see the package for the first time
- // sendPackageAddedForNewUsers also deals with system apps
- int appId = UserHandle.getAppId(request.getAppId());
- boolean isSystem = request.isInstallSystem();
- mPm.sendPackageAddedForNewUsers(mPm.snapshotComputer(), packageName,
- isSystem || virtualPreload, virtualPreload /*startReceiver*/, appId,
- firstUserIds, firstInstantUserIds, archived, dataLoaderType);
-
- // Send PACKAGE_ADDED broadcast for users that don't see
- // the package for the first time
-
- // Send to all running apps.
- final SparseArray<int[]> newBroadcastAllowList;
- synchronized (mPm.mLock) {
- final Computer snapshot = mPm.snapshotComputer();
- newBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(snapshot,
- snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
- updateUserIds, mPm.mSettings.getPackagesLocked());
- }
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, 0 /*flags*/,
- null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, newBroadcastAllowList, null);
- // Send to the installer, even if it's not running.
- if (installerPackageName != null) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, 0 /*flags*/,
- installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
- }
- // Send to PermissionController for all update users, even if it may not be running
- // for some users
- if (BroadcastHelper.isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, 0 /*flags*/,
- mPm.mRequiredPermissionControllerPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
- }
- // Notify required verifier(s) that are not the installer of record for the package.
- for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
- if (verifierPackageName != null && !verifierPackageName.equals(
- installerPackageName)) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, 0 /*flags*/,
- verifierPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /* broadcastAllowList */,
- null);
- }
- }
- // If package installer is defined, notify package installer about new
- // app installed
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
- mPm.mRequiredInstallerPackage, null /*finishedReceiver*/,
- firstUserIds, instantUserIds, null /* broadcastAllowList */, null);
-
- // Send replaced for users that don't see the package for the first time
- if (update) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- packageName, extras, 0 /*flags*/,
- null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds,
- request.getRemovedInfo().mBroadcastAllowList, null);
- if (installerPackageName != null) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
- extras, 0 /*flags*/,
- installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /*broadcastAllowList*/,
- null);
- }
- for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
- if (verifierPackageName != null && !verifierPackageName.equals(
- installerPackageName)) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- packageName, extras, 0 /*flags*/, verifierPackageName,
- null /*finishedReceiver*/, updateUserIds, instantUserIds,
- null /*broadcastAllowList*/, null);
- }
- }
- mPm.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
- null /*package*/, null /*extras*/, 0 /*flags*/,
- packageName /*targetPackage*/,
- null /*finishedReceiver*/, updateUserIds, instantUserIds,
- null /*broadcastAllowList*/,
- mBroadcastHelper.getTemporaryAppAllowlistBroadcastOptions(
- REASON_PACKAGE_REPLACED).toBundle());
- } else if (launchedForRestore && !request.isInstallSystem()) {
- // First-install and we did a restore, so we're responsible for the
- // first-launch broadcast.
- if (DEBUG_BACKUP) {
- Slog.i(TAG, "Post-restore of " + packageName
- + " sending FIRST_LAUNCH in " + Arrays.toString(firstUserIds));
- }
- mBroadcastHelper.sendFirstLaunchBroadcast(packageName, installerPackage,
- firstUserIds, firstInstantUserIds);
- }
-
- // Send broadcast package appeared if external for all users
- if (request.getPkg().isExternalStorage()) {
- if (!update) {
- final StorageManager storageManager =
- mInjector.getSystemService(StorageManager.class);
- VolumeInfo volume =
- storageManager.findVolumeByUuid(
- StorageManager.convert(
- request.getPkg().getVolumeUuid()).toString());
- int packageExternalStorageType =
- PackageManagerServiceUtils.getPackageExternalStorageType(volume,
- request.getPkg().isExternalStorage());
- // If the package was installed externally, log it.
- if (packageExternalStorageType != StorageEnums.UNKNOWN) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
- packageExternalStorageType, packageName);
- }
- }
- if (DEBUG_INSTALL) {
- Slog.i(TAG, "upgrading pkg " + request.getPkg() + " is external");
- }
- if (!archived) {
- final String[] pkgNames = new String[]{packageName};
- final int[] uids = new int[]{request.getPkg().getUid()};
- mBroadcastHelper.sendResourcesChangedBroadcast(mPm::snapshotComputer,
- true /* mediaStatus */, true /* replacing */, pkgNames, uids);
- mPm.notifyResourcesChanged(true /* mediaStatus */, true /* replacing */,
- pkgNames, uids);
- }
- }
- } else if (!ArrayUtils.isEmpty(request.getLibraryConsumers())) { // if static shared lib
- // No need to kill consumers if it's installation of new version static shared lib.
- final Computer snapshot = mPm.snapshotComputer();
- final boolean dontKillApp = !update
- && request.getPkg().getStaticSharedLibraryName() != null;
- for (int i = 0; i < request.getLibraryConsumers().size(); i++) {
- AndroidPackage pkg = request.getLibraryConsumers().get(i);
- // send broadcast that all consumers of the static shared library have changed
- mPm.sendPackageChangedBroadcast(snapshot, pkg.getPackageName(), dontKillApp,
- new ArrayList<>(Collections.singletonList(pkg.getPackageName())),
- pkg.getUid(), null);
- }
}
+ mBroadcastHelper.sendPostInstallBroadcasts(mPm.snapshotComputer(), request, packageName,
+ mPm.mRequiredPermissionControllerPackage, mPm.mRequiredVerifierPackages,
+ mPm.mRequiredInstallerPackage,
+ /* packageSender= */ mPm, launchedForRestore, killApp, update, archived);
+
+
// Work that needs to happen on first install within each user
if (firstUserIds.length > 0) {
for (int userId : firstUserIds) {
@@ -3074,7 +2879,6 @@
}
if (!archived) {
- final Computer snapshot = mPm.snapshotComputer();
// Notify DexManager that the package was installed for new users.
// The updated users should already be indexed and the package code paths
// should not change.
@@ -3090,7 +2894,7 @@
}
} else {
// Now send PACKAGE_REMOVED + EXTRA_REPLACING broadcast.
- final PackageRemovedInfo info = new PackageRemovedInfo(mPm);
+ final PackageRemovedInfo info = new PackageRemovedInfo();
info.mRemovedPackage = packageName;
info.mInstallerPackageName = request.getInstallerPackageName();
info.mRemovedUsers = firstUserIds;
@@ -3099,8 +2903,8 @@
info.mRemovedPackageVersionCode = request.getPkg().getLongVersionCode();
info.mRemovedForAllUsers = true;
- info.sendPackageRemovedBroadcasts(false /*killApp*/,
- false /*removedBySystem*/, true /*isArchived*/);
+ mBroadcastHelper.sendPackageRemovedBroadcasts(info, mPm,
+ false /*killApp*/, false /*removedBySystem*/, true /*isArchived*/);
}
}
@@ -3291,15 +3095,14 @@
synchronized (mPm.mLock) {
mPm.mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/);
}
- final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
- removePackageHelper.removePackage(stubPkg, true /*chatty*/);
+ mRemovePackageHelper.removePackage(stubPkg, true /*chatty*/);
try {
return initPackageTracedLI(scanFile, parseFlags, scanFlags);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(),
e);
// Remove the failed install
- removePackageHelper.removeCodePath(scanFile);
+ mRemovePackageHelper.removeCodePath(scanFile);
throw e;
}
}
@@ -3342,7 +3145,7 @@
if (!dstCodePath.exists()) {
return null;
}
- new RemovePackageHelper(mPm).removeCodePath(dstCodePath);
+ mRemovePackageHelper.removeCodePath(dstCodePath);
return null;
}
@@ -4298,8 +4101,8 @@
parsedPackage.getPackageName(), UserHandle.USER_ALL,
"scanPackageInternalLI", ApplicationExitInfo.REASON_OTHER,
null /* request */)) {
- DeletePackageHelper deletePackageHelper = new DeletePackageHelper(mPm);
- deletePackageHelper.deletePackageLIF(parsedPackage.getPackageName(), null, true,
+ mDeletePackageHelper.deletePackageLIF(
+ parsedPackage.getPackageName(), null, true,
mPm.mUserManager.getUserIds(), 0, null, false);
}
} else if (newPkgVersionGreater || newSharedUserSetting) {
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index fe6a8a1..ca8dc29 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -94,8 +94,6 @@
private final UserHandle mUser;
@NonNull
final PackageManagerService mPm;
- final InstallPackageHelper mInstallPackageHelper;
- final RemovePackageHelper mRemovePackageHelper;
final boolean mIsInherit;
final int mSessionId;
final int mRequireUserAction;
@@ -108,8 +106,6 @@
PackageLite packageLite, PackageManagerService pm) {
mPm = pm;
mUser = user;
- mInstallPackageHelper = new InstallPackageHelper(mPm);
- mRemovePackageHelper = new RemovePackageHelper(mPm);
mOriginInfo = originInfo;
mMoveInfo = moveInfo;
mObserver = observer;
@@ -142,8 +138,6 @@
PackageLite packageLite, PackageManagerService pm) {
mPm = pm;
mUser = user;
- mInstallPackageHelper = new InstallPackageHelper(mPm);
- mRemovePackageHelper = new RemovePackageHelper(mPm);
mOriginInfo = OriginInfo.fromStagedFile(stagedDir);
mMoveInfo = null;
mInstallReason = fixUpInstallReason(
@@ -242,7 +236,7 @@
// state can change within this delay and hence we need to re-verify certain conditions.
boolean isStaged = (mInstallFlags & INSTALL_STAGED) != 0;
if (isStaged) {
- Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
+ Pair<Integer, String> ret = mPm.verifyReplacingVersionCode(
pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
mRet = ret.first;
if (mRet != INSTALL_SUCCEEDED) {
@@ -540,39 +534,39 @@
}
}
} else {
- mInstallPackageHelper.installPackagesTraced(installRequests);
+ mPm.installPackagesTraced(installRequests);
for (InstallRequest request : installRequests) {
doPostInstall(request);
}
}
for (InstallRequest request : installRequests) {
- mInstallPackageHelper.restoreAndPostInstall(request);
+ mPm.restoreAndPostInstall(request);
}
}
private void doPostInstall(InstallRequest request) {
if (mMoveInfo != null) {
if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
- mRemovePackageHelper.cleanUpForMoveInstall(mMoveInfo.mFromUuid,
+ mPm.cleanUpForMoveInstall(mMoveInfo.mFromUuid,
mMoveInfo.mPackageName, mMoveInfo.mFromCodePath);
} else {
- mRemovePackageHelper.cleanUpForMoveInstall(mMoveInfo.mToUuid,
+ mPm.cleanUpForMoveInstall(mMoveInfo.mToUuid,
mMoveInfo.mPackageName, mMoveInfo.mFromCodePath);
}
} else {
if (request.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) {
- mRemovePackageHelper.removeCodePath(request.getCodeFile());
+ mPm.removeCodePath(request.getCodeFile());
}
}
}
private void cleanUpForFailedInstall(InstallRequest request) {
if (request.isInstallMove()) {
- mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(),
+ mPm.cleanUpForMoveInstall(request.getMoveToUuid(),
request.getMovePackageName(), request.getMoveFromCodePath());
} else {
- mRemovePackageHelper.removeCodePath(request.getCodeFile());
+ mPm.removeCodePath(request.getCodeFile());
}
}
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index b4ca477..4ecbd15 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -60,14 +60,10 @@
*/
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
@@ -82,7 +78,7 @@
void doHandleMessage(Message msg) {
switch (msg.what) {
case SEND_PENDING_BROADCAST: {
- mInstallPackageHelper.sendPendingBroadcasts();
+ mPm.sendPendingBroadcasts();
break;
}
case POST_INSTALL: {
@@ -96,7 +92,7 @@
request.onInstallCompleted();
request.runPostInstallRunnable();
if (!request.isInstallExistingForUser()) {
- mInstallPackageHelper.handlePackagePostInstall(request, didRestore);
+ mPm.handlePackagePostInstall(request, didRestore);
} else if (DEBUG_INSTALL) {
// No post-install when we run restore from installExistingPackageForUser
Slog.i(TAG, "Nothing to do for post-install token " + msg.arg1);
@@ -107,7 +103,7 @@
case DEFERRED_NO_KILL_POST_DELETE: {
InstallArgs args = (InstallArgs) msg.obj;
if (args != null) {
- mRemovePackageHelper.cleanUpResources(args.mCodeFile, args.mInstructionSets);
+ mPm.cleanUpResources(args.mCodeFile, args.mInstructionSets);
}
} 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 95b565d..1bb20b47 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -18,7 +18,9 @@
import static android.app.admin.DevicePolicyResources.Strings.Core.PACKAGE_DELETED_BY_DO;
import static android.os.Process.INVALID_UID;
+
import static com.android.server.pm.PackageManagerService.SHELL_PACKAGE_NAME;
+
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -407,11 +409,10 @@
}
private void removeStagingDirs(ArraySet<File> stagingDirsToRemove) {
- final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
// Clean up orphaned staging directories
for (File stage : stagingDirsToRemove) {
Slog.w(TAG, "Deleting orphan stage " + stage);
- removePackageHelper.removeCodePath(stage);
+ mPm.removeCodePath(stage);
}
}
@@ -1320,9 +1321,8 @@
@Override
public void installExistingPackage(String packageName, int installFlags, int installReason,
IntentSender statusReceiver, int userId, List<String> allowListedPermissions) {
- final InstallPackageHelper installPackageHelper = new InstallPackageHelper(mPm);
- var result = installPackageHelper.installExistingPackageAsUser(packageName, userId,
+ var result = mPm.installExistingPackageAsUser(packageName, userId,
installFlags, installReason, allowListedPermissions, statusReceiver);
int returnCode = result.first;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 54a2e3ad..d0e5f96 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2449,14 +2449,13 @@
}
private void onSystemDataLoaderUnrecoverable() {
- final DeletePackageHelper deletePackageHelper = new DeletePackageHelper(mPm);
final String packageName = getPackageName();
if (TextUtils.isEmpty(packageName)) {
// The package has not been installed.
return;
}
mHandler.post(() -> {
- if (deletePackageHelper.deletePackageX(packageName,
+ if (mPm.deletePackageX(packageName,
PackageManager.VERSION_CODE_HIGHEST, UserHandle.USER_SYSTEM,
PackageManager.DELETE_ALL_USERS, true /*removedBySystem*/)
!= PackageManager.DELETE_SUCCEEDED) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 33cb85c..ddc8369 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -70,7 +70,6 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
@@ -98,6 +97,7 @@
import android.content.pm.InstantAppRequest;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.ComponentEnabledSetting;
@@ -115,6 +115,7 @@
import android.content.pm.UserInfo;
import android.content.pm.UserPackage;
import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VerifierInfo;
import android.content.pm.VersionedPackage;
import android.content.pm.overlay.OverlayPaths;
import android.content.pm.parsing.PackageLite;
@@ -985,7 +986,7 @@
private final DeletePackageHelper mDeletePackageHelper;
private final InitAppsHelper mInitAppsHelper;
private final AppDataHelper mAppDataHelper;
- private final InstallPackageHelper mInstallPackageHelper;
+ @NonNull private final InstallPackageHelper mInstallPackageHelper;
private final PreferredActivityHelper mPreferredActivityHelper;
private final ResolveIntentHelper mResolveIntentHelper;
private final DexOptHelper mDexOptHelper;
@@ -1715,7 +1716,8 @@
(i, pm) -> new CrossProfileIntentFilterHelper(i.getSettings(),
i.getUserManagerService(), i.getLock(), i.getUserManagerInternal(),
context),
- (i, pm) -> new UpdateOwnershipHelper());
+ (i, pm) -> new UpdateOwnershipHelper(),
+ (i, pm) -> new PackageMonitorCallbackHelper());
if (Build.VERSION.SDK_INT <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
@@ -2067,17 +2069,19 @@
mDomainVerificationManager.setConnection(mDomainVerificationConnection);
mBroadcastHelper = new BroadcastHelper(mInjector);
- mPackageMonitorCallbackHelper = new PackageMonitorCallbackHelper(mInjector);
+ mPackageMonitorCallbackHelper = injector.getPackageMonitorCallbackHelper();
mAppDataHelper = new AppDataHelper(this);
- mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper);
- mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper);
- mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper);
+ mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper, mBroadcastHelper);
+ mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper,
+ mBroadcastHelper);
+ mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper, mRemovePackageHelper,
+ mDeletePackageHelper, mBroadcastHelper);
mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager,
mInjector.getUserManagerInternal(), mDeletePackageHelper);
mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
- mPreferredActivityHelper = new PreferredActivityHelper(this);
+ mPreferredActivityHelper = new PreferredActivityHelper(this, mBroadcastHelper);
mResolveIntentHelper = new ResolveIntentHelper(mContext, mPreferredActivityHelper,
injector.getCompatibility(), mUserManager, mDomainVerificationManager,
mUserNeedsBadging, () -> mResolveInfo, () -> mInstantAppInstallerActivity,
@@ -2085,7 +2089,7 @@
mDexOptHelper = new DexOptHelper(this);
mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mUserManager,
mBroadcastHelper, mProtectedPackages);
- mDistractingPackageHelper = new DistractingPackageHelper(this, mInjector, mBroadcastHelper,
+ mDistractingPackageHelper = new DistractingPackageHelper(this, mBroadcastHelper,
mSuspendPackageHelper);
mStorageEventHelper = new StorageEventHelper(this, mDeletePackageHelper,
mRemovePackageHelper);
@@ -3078,38 +3082,6 @@
}
@Override
- public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
- final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
- final int[] userIds, int[] instantUserIds,
- @Nullable SparseArray<int[]> broadcastAllowList,
- @Nullable Bundle bOptions) {
- mHandler.post(() -> mBroadcastHelper.sendPackageBroadcast(action, pkg, extras, flags,
- targetPkg, finishedReceiver, userIds, instantUserIds, broadcastAllowList,
- null /* filterExtrasForReceiver */, bOptions));
- if (targetPkg == null) {
- // For some broadcast action, e.g. ACTION_PACKAGE_ADDED, this method will be called
- // many times to different targets, e.g. installer app, permission controller, other
- // registered apps. We should filter it to avoid calling back many times for the same
- // action. When the targetPkg is set, it sends the broadcast to specific app, e.g.
- // installer app or null for registered apps. The callback only need to send back to the
- // registered apps so we check the null condition here.
- notifyPackageMonitor(action, pkg, extras, userIds, instantUserIds, broadcastAllowList);
- }
- }
-
- void notifyPackageMonitor(String action, String pkg, Bundle extras, int[] userIds,
- int[] instantUserIds, SparseArray<int[]> broadcastAllowList) {
- mPackageMonitorCallbackHelper.notifyPackageMonitor(action, pkg, extras, userIds,
- instantUserIds, broadcastAllowList);
- }
-
- void notifyResourcesChanged(boolean mediaStatus, boolean replacing,
- @NonNull String[] pkgNames, @NonNull int[] uids) {
- mPackageMonitorCallbackHelper.notifyResourcesChanged(mediaStatus, replacing, pkgNames,
- uids);
- }
-
- @Override
public void notifyPackageAdded(String packageName, int uid) {
mPackageObserverHelper.notifyAdded(packageName, uid);
}
@@ -3125,64 +3097,6 @@
UserPackage.removeFromCache(UserHandle.getUserId(uid), packageName);
}
- void sendPackageAddedForUser(@NonNull Computer snapshot, String packageName,
- @NonNull PackageStateInternal packageState, int userId, boolean isArchived,
- int dataLoaderType) {
- final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
- final boolean isSystem = packageState.isSystem();
- final boolean isInstantApp = userState.isInstantApp();
- final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
- final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
- sendPackageAddedForNewUsers(snapshot, packageName, isSystem /*sendBootCompleted*/,
- false /*startReceiver*/, packageState.getAppId(), userIds, instantUserIds,
- isArchived, dataLoaderType);
-
- // Send a session commit broadcast
- final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
- info.installReason = userState.getInstallReason();
- info.appPackageName = packageName;
- sendSessionCommitBroadcast(info, userId);
- }
-
- @Override
- public void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName,
- boolean sendBootCompleted, boolean includeStopped, @AppIdInt int appId, int[] userIds,
- int[] instantUserIds, boolean isArchived, int dataLoaderType) {
- if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) {
- return;
- }
- SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList(snapshot,
- snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
- userIds, snapshot.getPackageStates());
- mHandler.post(
- () -> mBroadcastHelper.sendPackageAddedForNewUsers(packageName, appId, userIds,
- instantUserIds, isArchived, dataLoaderType, broadcastAllowList));
- mPackageMonitorCallbackHelper.notifyPackageAddedForNewUsers(packageName, appId, userIds,
- instantUserIds, isArchived, dataLoaderType, broadcastAllowList);
- if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
- mHandler.post(() -> {
- for (int userId : userIds) {
- mBroadcastHelper.sendBootCompletedBroadcastToSystemApp(
- packageName, includeStopped, userId);
- }
- }
- );
- }
- }
-
- private void sendApplicationHiddenForUser(String packageName, PackageStateInternal packageState,
- int userId) {
- final PackageRemovedInfo info = new PackageRemovedInfo(this);
- info.mRemovedPackage = packageName;
- info.mInstallerPackageName = packageState.getInstallSource().mInstallerPackageName;
- info.mRemovedUsers = new int[] {userId};
- info.mBroadcastUsers = new int[] {userId};
- info.mUid = UserHandle.getUid(userId, packageState.getAppId());
- info.mRemovedPackageVersionCode = packageState.getVersionCode();
- info.sendPackageRemovedBroadcasts(true /*killApp*/, false /*removedBySystem*/,
- false /*isArchived*/);
- }
-
boolean isUserRestricted(int userId, String restrictionKey) {
Bundle restrictions = mUserManager.getUserRestrictions(userId);
if (restrictions.getBoolean(restrictionKey, false)) {
@@ -3505,11 +3419,6 @@
}
}
- void postPreferredActivityChangedBroadcast(int userId) {
- mHandler.post(() -> mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId));
- }
-
-
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
@GuardedBy("mLock")
void clearPackagePreferredActivitiesLPw(String packageName,
@@ -3609,17 +3518,8 @@
}
public void sendSessionCommitBroadcast(PackageInstaller.SessionInfo sessionInfo, int userId) {
- UserManagerService ums = UserManagerService.getInstance();
- if (ums == null || sessionInfo.isStaged()) {
- return;
- }
- final UserInfo parent = ums.getProfileParent(userId);
- final int launcherUid = (parent != null) ? parent.id : userId;
- // TODO: Should this snapshot be moved further up?
- final ComponentName launcherComponent = snapshotComputer()
- .getDefaultHomeActivity(launcherUid);
- mBroadcastHelper.sendSessionCommitBroadcast(sessionInfo, userId, launcherUid,
- launcherComponent, mAppPredictionServicePackage);
+ mBroadcastHelper.sendSessionCommitBroadcast(snapshotComputer(), sessionInfo, userId,
+ mAppPredictionServicePackage);
}
private @Nullable String getSetupWizardPackageNameImpl(@NonNull Computer computer) {
@@ -3988,7 +3888,7 @@
if (isSystemStub
&& (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
- if (!mInstallPackageHelper.enableCompressedPackage(deletedPkg, pkgSetting)) {
+ if (!enableCompressedPackage(deletedPkg, pkgSetting)) {
Slog.w(TAG, "Failed setApplicationEnabledSetting: failed to enable "
+ "commpressed package " + setting.getPackageName());
updateAllowed[i] = false;
@@ -4070,8 +3970,8 @@
final ArrayList<String> components = sendNowBroadcasts.valueAt(i);
final int packageUid = UserHandle.getUid(
userId, pkgSettings.get(packageName).getAppId());
- sendPackageChangedBroadcast(newSnapshot, packageName, false /* dontKillApp */,
- components, packageUid, null /* reason */);
+ mBroadcastHelper.sendPackageChangedBroadcast(newSnapshot, packageName,
+ false /* dontKillApp */, components, packageUid, null /* reason */);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -4147,27 +4047,6 @@
}
}
- void sendPackageChangedBroadcast(@NonNull Computer snapshot, String packageName,
- boolean dontKillApp, ArrayList<String> componentNames, int packageUid, String reason) {
- PackageStateInternal setting = snapshot.getPackageStateInternal(packageName,
- Process.SYSTEM_UID);
- if (setting == null) {
- return;
- }
- final int userId = UserHandle.getUserId(packageUid);
- final boolean isInstantApp =
- snapshot.isInstantAppInternal(packageName, userId, Process.SYSTEM_UID);
- final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
- final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
- final SparseArray<int[]> broadcastAllowList =
- isInstantApp ? null : snapshot.getVisibilityAllowLists(packageName, userIds);
- mHandler.post(() -> mBroadcastHelper.sendPackageChangedBroadcast(
- packageName, dontKillApp, componentNames, packageUid, reason, userIds,
- instantUserIds, broadcastAllowList));
- mPackageMonitorCallbackHelper.notifyPackageChanged(packageName, dontKillApp, componentNames,
- packageUid, reason, userIds, instantUserIds, broadcastAllowList);
- }
-
/**
* Used by SystemServer
*/
@@ -4312,7 +4191,7 @@
if (pkg == null) {
return;
}
- sendPackageChangedBroadcast(snapshot, pkg.getPackageName(),
+ mBroadcastHelper.sendPackageChangedBroadcast(snapshot, pkg.getPackageName(),
true /* dontKillApp */,
new ArrayList<>(Collections.singletonList(pkg.getPackageName())),
pkg.getUid(),
@@ -5294,7 +5173,7 @@
throw new SecurityException("Calling package " + packageName
+ " does not belong to calling uid " + callingUid);
}
- return mSuspendPackageHelper
+ return SuspendPackageHelper
.getSuspendedPackageAppExtras(snapshot, packageName, userId, callingUid);
}
@@ -5857,10 +5736,14 @@
if (hidden) {
killApplication(packageName, newPackageState.getAppId(), userId, "hiding pkg",
ApplicationExitInfo.REASON_OTHER);
- sendApplicationHiddenForUser(packageName, newPackageState, userId);
+ mBroadcastHelper.sendApplicationHiddenForUser(
+ packageName, newPackageState, userId,
+ /* packageSender= */ PackageManagerService.this);
} else {
- sendPackageAddedForUser(newSnapshot, packageName, newPackageState, userId,
- false /* isArchived */, DataLoaderType.NONE);
+ mBroadcastHelper.sendPackageAddedForUser(
+ newSnapshot, packageName, newPackageState, userId,
+ false /* isArchived */, DataLoaderType.NONE,
+ mAppPredictionServicePackage);
}
scheduleWritePackageRestrictions(userId);
@@ -7929,4 +7812,75 @@
}
}
}
+
+ void removeCodePath(@Nullable File codePath) {
+ mRemovePackageHelper.removeCodePath(codePath);
+ }
+
+ void cleanUpResources(@Nullable File codeFile, @Nullable String[] instructionSets) {
+ mRemovePackageHelper.cleanUpResources(codeFile, instructionSets);
+ }
+
+ void cleanUpForMoveInstall(String volumeUuid, String packageName, String fromCodePath) {
+ mRemovePackageHelper.cleanUpForMoveInstall(volumeUuid, packageName, fromCodePath);
+ }
+
+ void sendPendingBroadcasts() {
+ mInstallPackageHelper.sendPendingBroadcasts();
+ }
+
+ void handlePackagePostInstall(@NonNull InstallRequest request, boolean launchedForRestore) {
+ mInstallPackageHelper.handlePackagePostInstall(request, launchedForRestore);
+ }
+
+ Pair<Integer, IntentSender> installExistingPackageAsUser(
+ @Nullable String packageName,
+ @UserIdInt int userId, @PackageManager.InstallFlags int installFlags,
+ @PackageManager.InstallReason int installReason,
+ @Nullable List<String> allowlistedRestrictedPermissions,
+ @Nullable IntentSender intentSender) {
+ return mInstallPackageHelper.installExistingPackageAsUser(packageName, userId, installFlags,
+ installReason, allowlistedRestrictedPermissions, intentSender);
+ }
+ AndroidPackage initPackageTracedLI(File scanFile, final int parseFlags, int scanFlags)
+ throws PackageManagerException {
+ return mInstallPackageHelper.initPackageTracedLI(scanFile, parseFlags, scanFlags);
+ }
+
+ void restoreDisabledSystemPackageLIF(@NonNull DeletePackageAction action,
+ @NonNull int[] allUserHandles,
+ boolean writeSettings) throws SystemDeleteException {
+ mInstallPackageHelper.restoreDisabledSystemPackageLIF(
+ action, allUserHandles, writeSettings);
+ }
+ boolean enableCompressedPackage(@NonNull AndroidPackage stubPkg,
+ @NonNull PackageSetting stubPs) {
+ return mInstallPackageHelper.enableCompressedPackage(stubPkg, stubPs);
+ }
+
+ void installPackagesTraced(List<InstallRequest> requests) {
+ mInstallPackageHelper.installPackagesTraced(requests);
+ }
+
+ void restoreAndPostInstall(InstallRequest request) {
+ mInstallPackageHelper.restoreAndPostInstall(request);
+ }
+
+ Pair<Integer, String> verifyReplacingVersionCode(@NonNull PackageInfoLite pkgLite,
+ long requiredInstalledVersionCode,
+ int installFlags) {
+ return mInstallPackageHelper.verifyReplacingVersionCode(
+ pkgLite, requiredInstalledVersionCode, installFlags);
+ }
+
+ int getUidForVerifier(VerifierInfo verifierInfo) {
+ return mInstallPackageHelper.getUidForVerifier(verifierInfo);
+ }
+
+ int deletePackageX(String packageName, long versionCode, int userId, int deleteFlags,
+ boolean removedBySystem) {
+ return mDeletePackageHelper.deletePackageX(packageName,
+ PackageManager.VERSION_CODE_HIGHEST, UserHandle.USER_SYSTEM,
+ PackageManager.DELETE_ALL_USERS, true /*removedBySystem*/);
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
index 0c2e082..5b770aab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
@@ -146,6 +146,7 @@
private final Singleton<SharedLibrariesImpl> mSharedLibrariesProducer;
private final Singleton<CrossProfileIntentFilterHelper> mCrossProfileIntentFilterHelperProducer;
private final Singleton<UpdateOwnershipHelper> mUpdateOwnershipHelperProducer;
+ private final Singleton<PackageMonitorCallbackHelper> mPackageMonitorCallbackHelper;
PackageManagerServiceInjector(Context context, PackageManagerTracedLock lock,
Installer installer, Object installLock, PackageAbiHelper abiHelper,
@@ -186,7 +187,8 @@
Producer<IBackupManager> iBackupManager,
Producer<SharedLibrariesImpl> sharedLibrariesProducer,
Producer<CrossProfileIntentFilterHelper> crossProfileIntentFilterHelperProducer,
- Producer<UpdateOwnershipHelper> updateOwnershipHelperProducer) {
+ Producer<UpdateOwnershipHelper> updateOwnershipHelperProducer,
+ Producer<PackageMonitorCallbackHelper> packageMonitorCallbackHelper) {
mContext = context;
mLock = lock;
mInstaller = installer;
@@ -242,6 +244,7 @@
mCrossProfileIntentFilterHelperProducer = new Singleton<>(
crossProfileIntentFilterHelperProducer);
mUpdateOwnershipHelperProducer = new Singleton<>(updateOwnershipHelperProducer);
+ mPackageMonitorCallbackHelper = new Singleton<>(packageMonitorCallbackHelper);
}
/**
@@ -431,6 +434,10 @@
return mUpdateOwnershipHelperProducer.get(this, mPackageManager);
}
+ public PackageMonitorCallbackHelper getPackageMonitorCallbackHelper() {
+ return mPackageMonitorCallbackHelper.get(this, mPackageManager);
+ }
+
/** Provides an abstraction to static access to system state. */
public interface SystemWrapper {
diff --git a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
index bb3bf53..b8c2b86 100644
--- a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
+++ b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
@@ -52,12 +52,6 @@
private final Object mLock = new Object();
final IActivityManager mActivityManager = ActivityManager.getService();
- final Handler mHandler;
-
- PackageMonitorCallbackHelper(PackageManagerServiceInjector injector) {
- mHandler = injector.getHandler();
- }
-
@NonNull
@GuardedBy("mLock")
private final RemoteCallbackList<IRemoteCallback> mCallbacks = new RemoteCallbackList<>();
@@ -100,7 +94,8 @@
public void notifyPackageAddedForNewUsers(String packageName,
@AppIdInt int appId, @NonNull int[] userIds, @NonNull int[] instantUserIds,
- boolean isArchived, int dataLoaderType, SparseArray<int[]> broadcastAllowList) {
+ boolean isArchived, int dataLoaderType, SparseArray<int[]> broadcastAllowList,
+ @NonNull Handler handler) {
Bundle extras = new Bundle(2);
// Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
final int uid = UserHandle.getUid(
@@ -111,11 +106,11 @@
}
extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED, packageName, extras ,
- userIds /* userIds */, instantUserIds, broadcastAllowList);
+ userIds /* userIds */, instantUserIds, broadcastAllowList, handler);
}
public void notifyResourcesChanged(boolean mediaStatus, boolean replacing,
- @NonNull String[] pkgNames, @NonNull int[] uids) {
+ @NonNull String[] pkgNames, @NonNull int[] uids, @NonNull Handler handler) {
Bundle extras = new Bundle();
extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgNames);
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids);
@@ -125,12 +120,12 @@
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
notifyPackageMonitor(action, null /* pkg */, extras, null /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, handler);
}
public void notifyPackageChanged(String packageName, boolean dontKillApp,
ArrayList<String> componentNames, int packageUid, String reason, int[] userIds,
- int[] instantUserIds, SparseArray<int[]> broadcastAllowList) {
+ int[] instantUserIds, SparseArray<int[]> broadcastAllowList, Handler handler) {
Bundle extras = new Bundle(4);
extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
String[] nameList = new String[componentNames.size()];
@@ -142,11 +137,12 @@
extras.putString(Intent.EXTRA_REASON, reason);
}
notifyPackageMonitor(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, userIds,
- instantUserIds, broadcastAllowList);
+ instantUserIds, broadcastAllowList, handler);
}
public void notifyPackageMonitor(String action, String pkg, Bundle extras,
- int[] userIds, int[] instantUserIds, SparseArray<int[]> broadcastAllowList) {
+ int[] userIds, int[] instantUserIds, SparseArray<int[]> broadcastAllowList,
+ Handler handler) {
if (!isAllowedCallbackAction(action)) {
return;
}
@@ -160,9 +156,10 @@
}
if (ArrayUtils.isEmpty(instantUserIds)) {
- doNotifyCallbacks(action, pkg, extras, resolvedUserIds, broadcastAllowList);
+ doNotifyCallbacks(
+ action, pkg, extras, resolvedUserIds, broadcastAllowList, handler);
} else {
- doNotifyCallbacks(action, pkg, extras, instantUserIds, broadcastAllowList);
+ doNotifyCallbacks(action, pkg, extras, instantUserIds, broadcastAllowList, handler);
}
} catch (RemoteException e) {
// do nothing
@@ -181,7 +178,7 @@
}
private void doNotifyCallbacks(String action, String pkg, Bundle extras, int[] userIds,
- SparseArray<int[]> broadcastAllowList) {
+ SparseArray<int[]> broadcastAllowList, Handler handler) {
RemoteCallbackList<IRemoteCallback> callbacks;
synchronized (mLock) {
callbacks = mCallbacks;
@@ -202,7 +199,7 @@
final int[] allowUids =
broadcastAllowList != null ? broadcastAllowList.get(userId) : new int[]{};
- mHandler.post(() -> callbacks.broadcast((callback, user) -> {
+ handler.post(() -> callbacks.broadcast((callback, user) -> {
RegisterUser registerUser = (RegisterUser) user;
if ((registerUser.getUserId() != UserHandle.USER_ALL) && (registerUser.getUserId()
!= userId)) {
diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
index 9f02542..7ee1772 100644
--- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java
+++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
@@ -16,24 +16,12 @@
package com.android.server.pm;
-import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
-import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
-import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
-
-import android.annotation.NonNull;
-import android.app.ActivityManagerInternal;
-import android.app.BroadcastOptions;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.PowerExemptionManager;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.util.ArrayUtils;
-import com.android.server.LocalServices;
final class PackageRemovedInfo {
- final PackageSender mPackageSender;
String mRemovedPackage;
String mInstallerPackageName;
int mUid = -1;
@@ -58,116 +46,6 @@
InstallArgs mArgs = null;
private static final int[] EMPTY_INT_ARRAY = new int[0];
- PackageRemovedInfo(PackageSender packageSender) {
- mPackageSender = packageSender;
- }
-
- void sendPackageRemovedBroadcasts(boolean killApp, boolean removedBySystem,
- boolean isArchived) {
- sendPackageRemovedBroadcastInternal(killApp, removedBySystem, isArchived);
- }
-
- void sendSystemPackageUpdatedBroadcasts() {
- if (mIsRemovedPackageSystemUpdate) {
- sendSystemPackageUpdatedBroadcastsInternal();
- }
- }
-
- private void sendSystemPackageUpdatedBroadcastsInternal() {
- Bundle extras = new Bundle(2);
- extras.putInt(Intent.EXTRA_UID, mRemovedAppId >= 0 ? mRemovedAppId : mUid);
- extras.putBoolean(Intent.EXTRA_REPLACING, true);
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, mRemovedPackage, extras,
- 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
- if (mInstallerPackageName != null) {
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- mRemovedPackage, extras, 0 /*flags*/,
- mInstallerPackageName, null, null, null, null /* broadcastAllowList */,
- null);
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- mRemovedPackage, extras, 0 /*flags*/,
- mInstallerPackageName, null, null, null, null /* broadcastAllowList */,
- null);
- }
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, mRemovedPackage,
- extras, 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
- mPackageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
- mRemovedPackage, null, null, null, null /* broadcastAllowList */,
- getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED).toBundle());
- }
-
- private static @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
- @PowerExemptionManager.ReasonCode int reasonCode) {
- long duration = 10_000;
- final ActivityManagerInternal amInternal =
- LocalServices.getService(ActivityManagerInternal.class);
- if (amInternal != null) {
- duration = amInternal.getBootTimeTempAllowListDuration();
- }
- final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
- bOptions.setTemporaryAppAllowlist(duration,
- TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
- reasonCode, "");
- return bOptions;
- }
-
- private void sendPackageRemovedBroadcastInternal(boolean killApp, boolean removedBySystem,
- boolean isArchived) {
- Bundle extras = new Bundle();
- final int removedUid = mRemovedAppId >= 0 ? mRemovedAppId : mUid;
- extras.putInt(Intent.EXTRA_UID, removedUid);
- extras.putBoolean(Intent.EXTRA_DATA_REMOVED, mDataRemoved);
- extras.putBoolean(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, mIsRemovedPackageSystemUpdate);
- extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
- extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem);
- final boolean isReplace = mIsUpdate || mIsRemovedPackageSystemUpdate;
- if (isReplace || isArchived) {
- extras.putBoolean(Intent.EXTRA_REPLACING, true);
- }
- if (isArchived) {
- extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
- }
- extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, mRemovedForAllUsers);
-
- // Send PACKAGE_REMOVED broadcast to the respective installer.
- if (mRemovedPackage != null && mInstallerPackageName != null) {
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
- mRemovedPackage, extras, 0 /*flags*/,
- mInstallerPackageName, null, mBroadcastUsers, mInstantUserIds, null, null);
- }
- if (mIsStaticSharedLib) {
- // When uninstalling static shared libraries, only the package's installer needs to be
- // sent a PACKAGE_REMOVED broadcast. There are no other intended recipients.
- return;
- }
- if (mRemovedPackage != null) {
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
- mRemovedPackage, extras, 0, null /*targetPackage*/, null,
- mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null);
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED_INTERNAL,
- mRemovedPackage, extras, 0 /*flags*/, PLATFORM_PACKAGE_NAME,
- null /*finishedReceiver*/, mBroadcastUsers, mInstantUserIds,
- mBroadcastAllowList, null /*bOptions*/);
- if (mDataRemoved && !mIsRemovedPackageSystemUpdate) {
- mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
- mRemovedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
- null, mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null);
- mPackageSender.notifyPackageRemoved(mRemovedPackage, removedUid);
- }
- }
- if (mRemovedAppId >= 0) {
- // If a system app's updates are uninstalled the UID is not actually removed. Some
- // services need to know the package name affected.
- if (isReplace) {
- extras.putString(Intent.EXTRA_PACKAGE_NAME, mRemovedPackage);
- }
-
- mPackageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED,
- null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null);
- }
- }
-
public void populateBroadcastUsers(PackageSetting deletedPackageSetting) {
if (mRemovedUsers == null) {
mBroadcastUsers = null;
diff --git a/services/core/java/com/android/server/pm/PackageSender.java b/services/core/java/com/android/server/pm/PackageSender.java
index 82e1d5f3..db83f59 100644
--- a/services/core/java/com/android/server/pm/PackageSender.java
+++ b/services/core/java/com/android/server/pm/PackageSender.java
@@ -16,24 +16,7 @@
package com.android.server.pm;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.IIntentReceiver;
-import android.os.Bundle;
-import android.util.SparseArray;
-
interface PackageSender {
- /**
- * @param userIds User IDs where the action occurred on a full application
- * @param instantUserIds User IDs where the action occurred on an instant application
- */
- void sendPackageBroadcast(String action, String pkg,
- Bundle extras, int flags, String targetPkg,
- IIntentReceiver finishedReceiver, int[] userIds, int[] instantUserIds,
- @Nullable SparseArray<int[]> broadcastAllowList, @Nullable Bundle bOptions);
- void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName,
- boolean sendBootCompleted, boolean includeStopped, int appId, int[] userIds,
- int[] instantUserIds, boolean isArchived, int dataLoaderType);
void notifyPackageAdded(String packageName, int uid);
void notifyPackageChanged(String packageName, int uid);
void notifyPackageRemoved(String packageName, int uid);
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index 571aab4..41d2aeb 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -69,10 +69,12 @@
private static final String TAG_DEFAULT_APPS = "da";
private final PackageManagerService mPm;
+ private final BroadcastHelper mBroadcastHelper;
// TODO(b/198166813): remove PMS dependency
- PreferredActivityHelper(PackageManagerService pm) {
+ PreferredActivityHelper(PackageManagerService pm, BroadcastHelper broadcastHelper) {
mPm = pm;
+ mBroadcastHelper = broadcastHelper;
}
private ResolveInfo findPreferredActivityNotLocked(@NonNull Computer snapshot, Intent intent,
@@ -120,7 +122,7 @@
}
if (changedUsers.size() > 0) {
updateDefaultHomeNotLocked(mPm.snapshotComputer(), changedUsers);
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
mPm.scheduleWritePackageRestrictions(userId);
}
}
@@ -167,7 +169,7 @@
return mPm.setActiveLauncherPackage(packageName, userId,
successful -> {
if (successful) {
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
}
});
}
@@ -215,7 +217,7 @@
}
// Re-snapshot after mLock
if (!(isHomeFilter(filter) && updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId))) {
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
}
}
@@ -411,7 +413,7 @@
if (isHomeFilter(filter)) {
updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId);
}
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
}
public void clearPackagePersistentPreferredActivities(String packageName, int userId) {
@@ -426,7 +428,7 @@
}
if (changed) {
updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId);
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
mPm.scheduleWritePackageRestrictions(userId);
}
}
@@ -443,7 +445,7 @@
}
if (changed) {
updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId);
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
mPm.scheduleWritePackageRestrictions(userId);
}
}
@@ -616,7 +618,7 @@
mPm.clearPackagePreferredActivitiesLPw(null, changedUsers, userId);
}
if (changedUsers.size() > 0) {
- mPm.postPreferredActivityChangedBroadcast(userId);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId);
}
synchronized (mPm.mLock) {
mPm.mSettings.applyDefaultPreferredAppsLPw(userId);
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index d989c90..3d61f3e 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -22,6 +22,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;
@@ -69,9 +70,11 @@
private final PermissionManagerServiceInternal mPermissionManager;
private final SharedLibrariesImpl mSharedLibraries;
private final AppDataHelper mAppDataHelper;
+ private final BroadcastHelper mBroadcastHelper;
// TODO(b/198166813): remove PMS dependency
- RemovePackageHelper(PackageManagerService pm, AppDataHelper appDataHelper) {
+ RemovePackageHelper(PackageManagerService pm, AppDataHelper appDataHelper,
+ BroadcastHelper broadcastHelper) {
mPm = pm;
mIncrementalManager = mPm.mInjector.getIncrementalManager();
mInstaller = mPm.mInjector.getInstaller();
@@ -79,10 +82,7 @@
mPermissionManager = mPm.mInjector.getPermissionManagerServiceInternal();
mSharedLibraries = mPm.mInjector.getSharedLibrariesImpl();
mAppDataHelper = appDataHelper;
- }
-
- RemovePackageHelper(PackageManagerService pm) {
- this(pm, new AppDataHelper(pm));
+ mBroadcastHelper = broadcastHelper;
}
public void removeCodePath(File codePath) {
@@ -265,7 +265,8 @@
final List<AndroidPackage> sharedUserPkgs =
sus != null ? sus.getPackages() : Collections.emptyList();
- final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm);
+ final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm,
+ mBroadcastHelper);
final int[] userIds = (userId == UserHandle.USER_ALL) ? mUserManagerInternal.getUserIds()
: new int[] {userId};
for (int nextUserId : userIds) {
@@ -395,10 +396,10 @@
}
if (changedUsers.size() > 0) {
final PreferredActivityHelper preferredActivityHelper =
- new PreferredActivityHelper(mPm);
+ new PreferredActivityHelper(mPm, mBroadcastHelper);
preferredActivityHelper.updateDefaultHomeNotLocked(mPm.snapshotComputer(),
changedUsers);
- mPm.postPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
+ mBroadcastHelper.sendPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
}
} else if (!deletedPs.isSystem() && outInfo != null && !outInfo.mIsUpdate
&& outInfo.mRemovedUsers != null) {
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index db5b9b1..c725cdc 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -147,7 +147,6 @@
final Settings.VersionInfo ver;
final List<? extends PackageStateInternal> packages;
- final InstallPackageHelper installPackageHelper = new InstallPackageHelper(mPm);
synchronized (mPm.mLock) {
ver = mPm.mSettings.findOrCreateVersion(volumeUuid);
packages = mPm.mSettings.getVolumePackagesLPr(volumeUuid);
@@ -160,7 +159,7 @@
synchronized (mPm.mInstallLock) {
final AndroidPackage pkg;
try {
- pkg = installPackageHelper.initPackageTracedLI(
+ pkg = mPm.initPackageTracedLI(
ps.getPath(), parseFlags, SCAN_INITIAL);
loaded.add(pkg);
@@ -228,7 +227,8 @@
}
if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
- sendResourcesChangedBroadcast(true /* mediaStatus */, false /* replacing */, loaded);
+ mBroadcastHelper.sendResourcesChangedBroadcastAndNotify(mPm.snapshotComputer(),
+ true /* mediaStatus */, false /* replacing */, loaded);
synchronized (mLoadedVolumes) {
mLoadedVolumes.add(vol.getId());
}
@@ -256,7 +256,7 @@
final AndroidPackage pkg = ps.getPkg();
final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
- final PackageRemovedInfo outInfo = new PackageRemovedInfo(mPm);
+ final PackageRemovedInfo outInfo = new PackageRemovedInfo();
try (PackageFreezer freezer = mPm.freezePackageForDelete(ps.getPackageName(),
UserHandle.USER_ALL, deleteFlags,
@@ -280,7 +280,8 @@
}
if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
- sendResourcesChangedBroadcast(false /* mediaStatus */, false /* replacing */, unloaded);
+ mBroadcastHelper.sendResourcesChangedBroadcastAndNotify(mPm.snapshotComputer(),
+ false /* mediaStatus */, false /* replacing */, unloaded);
synchronized (mLoadedVolumes) {
mLoadedVolumes.remove(vol.getId());
}
@@ -295,21 +296,6 @@
}
}
- private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
- ArrayList<AndroidPackage> packages) {
- final int size = packages.size();
- final String[] packageNames = new String[size];
- final int[] packageUids = new int[size];
- for (int i = 0; i < size; i++) {
- final AndroidPackage pkg = packages.get(i);
- packageNames[i] = pkg.getPackageName();
- packageUids[i] = pkg.getUid();
- }
- mBroadcastHelper.sendResourcesChangedBroadcast(mPm::snapshotComputer, mediaStatus,
- replacing, packageNames, packageUids);
- mPm.notifyResourcesChanged(mediaStatus, replacing, packageNames, packageUids);
- }
-
/**
* Examine all apps present on given mounted volume, and destroy apps that
* aren't expected, either due to uninstallation or reinstallation on
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index ddb045d..29d99a73 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -26,17 +26,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.ActivityManager;
import android.app.AppOpsManager;
-import android.app.BroadcastOptions;
-import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.SuspendDialogInfo;
import android.os.Binder;
import android.os.Bundle;
-import android.os.Handler;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
@@ -47,7 +43,6 @@
import android.util.IntArray;
import android.util.Slog;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.server.LocalServices;
@@ -207,19 +202,22 @@
}
});
+ final Computer newSnapshot = mPm.snapshotComputer();
if (!notifyPackagesList.isEmpty()) {
final String[] changedPackages =
notifyPackagesList.toArray(new String[0]);
- sendPackagesSuspendedForUser(
+ mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(newSnapshot,
suspended ? Intent.ACTION_PACKAGES_SUSPENDED
: Intent.ACTION_PACKAGES_UNSUSPENDED,
changedPackages, notifyUids.toArray(), quarantined, userId);
- sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, userId);
+ mBroadcastHelper.sendMyPackageSuspendedOrUnsuspended(newSnapshot, changedPackages,
+ suspended, userId);
mPm.scheduleWritePackageRestrictions(userId);
}
// Send the suspension changed broadcast to ensure suspension state is not stale.
if (!changedPackagesList.isEmpty()) {
- sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED,
+ mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(newSnapshot,
+ Intent.ACTION_PACKAGES_SUSPENSION_CHANGED,
changedPackagesList.toArray(new String[0]), changedUids.toArray(), quarantined,
userId);
}
@@ -269,8 +267,10 @@
* @return The app extras of the suspended package.
*/
@Nullable
- Bundle getSuspendedPackageAppExtras(@NonNull Computer snapshot, @NonNull String packageName,
- int userId, int callingUid) {
+ static Bundle getSuspendedPackageAppExtras(@NonNull Computer snapshot,
+ @NonNull String packageName,
+ int userId,
+ int callingUid) {
final PackageStateInternal ps = snapshot.getPackageStateInternal(packageName, callingUid);
if (ps == null) {
return null;
@@ -299,7 +299,7 @@
* suspensions will be removed.
* @param userId The user for which the changes are taking place.
*/
- void removeSuspensionsBySuspendingPackage(@NonNull Computer computer,
+ void removeSuspensionsBySuspendingPackage(@NonNull Computer snapshot,
@NonNull String[] packagesToChange,
@NonNull Predicate<String> suspendingPackagePredicate, int userId) {
final List<String> unsuspendedPackages = new ArrayList<>();
@@ -307,7 +307,7 @@
final ArrayMap<String, ArraySet<String>> pkgToSuspendingPkgsToCommit = new ArrayMap<>();
for (String packageName : packagesToChange) {
final PackageStateInternal packageState =
- computer.getPackageStateInternal(packageName);
+ snapshot.getPackageStateInternal(packageName);
final PackageUserStateInternal packageUserState = packageState == null
? null : packageState.getUserStateOrDefault(userId);
if (packageUserState == null || !packageUserState.isSuspended()) {
@@ -350,11 +350,14 @@
});
mPm.scheduleWritePackageRestrictions(userId);
+ final Computer newSnapshot = mPm.snapshotComputer();
if (!unsuspendedPackages.isEmpty()) {
final String[] packageArray = unsuspendedPackages.toArray(
new String[unsuspendedPackages.size()]);
- sendMyPackageSuspendedOrUnsuspended(packageArray, false, userId);
- sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_UNSUSPENDED,
+ mBroadcastHelper.sendMyPackageSuspendedOrUnsuspended(newSnapshot, packageArray,
+ false, userId);
+ mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(newSnapshot,
+ Intent.ACTION_PACKAGES_UNSUSPENDED,
packageArray, unsuspendedUids.toArray(), false, userId);
}
}
@@ -610,38 +613,6 @@
}
/**
- * Send broadcast intents for packages suspension changes.
- *
- * @param intent The action name of the suspension intent.
- * @param pkgList The names of packages which have suspension changes.
- * @param uidList The uids of packages which have suspension changes.
- * @param userId The user where packages reside.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- void sendPackagesSuspendedForUser(@NonNull String intent, @NonNull String[] pkgList,
- @NonNull int[] uidList, boolean quarantined, int userId) {
- final Handler handler = mInjector.getHandler();
- final Bundle extras = new Bundle(3);
- extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
- extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
- if (quarantined) {
- extras.putBoolean(Intent.EXTRA_QUARANTINED, true);
- }
- final int flags = Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND;
- final Bundle options = new BroadcastOptions()
- .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
- .toBundle();
- handler.post(() -> mBroadcastHelper.sendPackageBroadcast(intent, null /* pkg */,
- extras, flags, null /* targetPkg */, null /* finishedReceiver */,
- new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */,
- (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
- mPm.snapshotComputer(), callingUid, intentExtras),
- options));
- mPm.notifyPackageMonitor(intent, null /* pkg */, extras, new int[]{userId},
- null /* instantUserIds */, null /* broadcastAllowList */);
- }
-
- /**
* Suspends packages on behalf of an admin.
*
* @return array of packages that are unsuspendable, either because admin is not allowed to
@@ -756,37 +727,4 @@
}
return false;
}
-
- private void sendMyPackageSuspendedOrUnsuspended(String[] affectedPackages, boolean suspended,
- int userId) {
- final Handler handler = mInjector.getHandler();
- final String action = suspended
- ? Intent.ACTION_MY_PACKAGE_SUSPENDED
- : Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
- handler.post(() -> {
- final IActivityManager am = ActivityManager.getService();
- if (am == null) {
- Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
- + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
- return;
- }
- final int[] targetUserIds = new int[] {userId};
- final Computer snapshot = mPm.snapshotComputer();
- for (String packageName : affectedPackages) {
- final Bundle appExtras = suspended
- ? getSuspendedPackageAppExtras(snapshot, packageName, userId, SYSTEM_UID)
- : null;
- final Bundle intentExtras;
- if (appExtras != null) {
- intentExtras = new Bundle(1);
- intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
- } else {
- intentExtras = null;
- }
- mBroadcastHelper.doSendBroadcast(action, null, intentExtras,
- Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
- targetUserIds, false, null, null, null);
- }
- });
- }
}
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 8c73ce8..c6435ae 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -139,7 +139,6 @@
private final UserHandle mUser;
@NonNull
private final PackageManagerService mPm;
- private final InstallPackageHelper mInstallPackageHelper;
VerifyingSession(UserHandle user, File stagedDir, IPackageInstallObserver2 observer,
PackageInstaller.SessionParams sessionParams, InstallSource installSource,
@@ -147,7 +146,6 @@
boolean userActionRequired, PackageManagerService pm) {
mPm = pm;
mUser = user;
- mInstallPackageHelper = new InstallPackageHelper(mPm);
mOriginInfo = OriginInfo.fromStagedFile(stagedDir);
mObserver = observer;
mInstallFlags = sessionParams.installFlags;
@@ -181,7 +179,7 @@
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mPm.mContext,
mPackageLite, mOriginInfo.mResolvedPath, mInstallFlags, mPackageAbiOverride);
- Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
+ Pair<Integer, String> ret = mPm.verifyReplacingVersionCode(
pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
setReturnCode(ret.first, ret.second);
if (mRet != INSTALL_SUCCEEDED) {
@@ -729,7 +727,7 @@
continue;
}
- final int verifierUid = mInstallPackageHelper.getUidForVerifier(verifierInfo);
+ final int verifierUid = mPm.getUidForVerifier(verifierInfo);
if (verifierUid == -1) {
continue;
}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
index 4a2bf75..5d3eba8 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -17,24 +17,22 @@
package com.android.server.pm;
import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+
import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
+
import static java.lang.reflect.Modifier.isFinal;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.AppGlobals;
-import android.content.IIntentReceiver;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Postsubmit;
-import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -87,18 +85,6 @@
@Test
public void testPackageRemoval() {
class PackageSenderImpl implements PackageSender {
- public void sendPackageBroadcast(final String action, final String pkg,
- final Bundle extras, final int flags, final String targetPkg,
- final IIntentReceiver finishedReceiver, final int[] userIds,
- int[] instantUserIds, SparseArray<int[]> broadcastAllowList,
- @Nullable Bundle bOptions) {
- }
-
- public void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName,
- boolean sendBootComplete, boolean includeStopped, int appId,
- int[] userIds, int[] instantUserIds, boolean isArchived, int dataLoaderType) {
- }
-
@Override
public void notifyPackageAdded(String packageName, int uid) {
}
@@ -113,9 +99,8 @@
}
}
- PackageSenderImpl sender = new PackageSenderImpl();
PackageSetting setting = null;
- PackageRemovedInfo pri = new PackageRemovedInfo(sender);
+ PackageRemovedInfo pri = new PackageRemovedInfo();
// Initial conditions: nothing there
Assert.assertNull(pri.mRemovedUsers);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
index 52044bf..de8b308 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -117,7 +117,9 @@
Build.VERSION_CODES.CUR_DEVELOPMENT,
Build.VERSION.INCREMENTAL);
mMockSystem.system().validateFinalState();
- mInstallPackageHelper = new InstallPackageHelper(mPmService, mock(AppDataHelper.class));
+ mInstallPackageHelper = new InstallPackageHelper(mPmService, mock(AppDataHelper.class),
+ mock(RemovePackageHelper.class), mock(DeletePackageHelper.class),
+ mock(BroadcastHelper.class));
}
@NonNull
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
index d6a4d40..931b38d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
@@ -34,6 +34,7 @@
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.mock
@RunWith(JUnit4::class)
class DeletePackageHelperTest {
@@ -79,7 +80,8 @@
whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(UserInfo(1, "test", 0))
whenever(mUserManagerInternal.getProfileParentId(1)).thenReturn(1)
- val dph = DeletePackageHelper(mPms)
+ val dph = DeletePackageHelper(mPms, mock(RemovePackageHelper::class.java),
+ mock(BroadcastHelper::class.java))
val result = dph.deletePackageX("a.data.package", 1L, 1, 0, false)
assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED)
@@ -97,7 +99,8 @@
whenever(mUserManagerInternal.getUserInfo(parentId)).thenReturn(
UserInfo(userId, "testparent", 0))
- val dph = DeletePackageHelper(mPms)
+ val dph = DeletePackageHelper(mPms, mock(RemovePackageHelper::class.java),
+ mock(BroadcastHelper::class.java))
val result = dph.deletePackageX("a.data.package", 1L, userId, 0, false)
assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED)
@@ -112,7 +115,8 @@
whenever(mPms.checkPermission(CONTROL_KEYGUARD, "a.data.package", USER_SYSTEM))
.thenReturn(PERMISSION_DENIED)
- val dph = DeletePackageHelper(mPms)
+ val dph = DeletePackageHelper(mPms, mock(RemovePackageHelper::class.java),
+ mock(BroadcastHelper::class.java))
val result = dph.deletePackageX("a.data.package", 1L, 1,
PackageManager.DELETE_SYSTEM_APP, false)
@@ -133,7 +137,8 @@
whenever(mPms.checkPermission(CONTROL_KEYGUARD, "a.data.package", USER_SYSTEM))
.thenReturn(PERMISSION_DENIED)
- val dph = DeletePackageHelper(mPms)
+ val dph = DeletePackageHelper(mPms, mock(RemovePackageHelper::class.java),
+ mock(BroadcastHelper::class.java))
val result = dph.deletePackageX("a.data.package", 1L, userId,
PackageManager.DELETE_SYSTEM_APP, false)
@@ -150,7 +155,8 @@
whenever(mPms.checkPermission(CONTROL_KEYGUARD, "a.data.package", USER_SYSTEM))
.thenReturn(PERMISSION_DENIED)
- val dph = DeletePackageHelper(mPms)
+ val dph = DeletePackageHelper(mPms, mock(RemovePackageHelper::class.java),
+ mock(BroadcastHelper::class.java))
val result = dph.deletePackageX("a.data.package", 1L, 1,
PackageManager.DELETE_SYSTEM_APP, false)
@@ -164,7 +170,8 @@
whenever(mPms.checkPermission(CONTROL_KEYGUARD, "a.data.package", USER_SYSTEM))
.thenReturn(PERMISSION_GRANTED)
- val dph = DeletePackageHelper(mPms)
+ val dph = DeletePackageHelper(mPms, mock(RemovePackageHelper::class.java),
+ mock(BroadcastHelper::class.java))
val result = dph.deletePackageX("a.data.package", 1L, 1,
PackageManager.DELETE_SYSTEM_APP, false)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt
index 9f1cec3..cf81f0a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt
@@ -39,7 +39,7 @@
override fun setup() {
super.setup()
distractingPackageHelper = DistractingPackageHelper(
- pms, rule.mocks().injector, broadcastHelper, suspendPackageHelper)
+ pms, broadcastHelper, suspendPackageHelper)
}
@Test
@@ -50,12 +50,11 @@
testHandler.flush()
verify(pms).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED),
- nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(),
- nullable(), nullable(), nullable(), nullable())
+ verify(broadcastHelper).sendDistractingPackagesChanged(any(Computer::class.java),
+ pkgListCaptor.capture(), any(), any(), flagsCaptor.capture())
- val modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
- val distractionFlags = bundleCaptor.value.getInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS)
+ val modifiedPackages = pkgListCaptor.value
+ val distractionFlags = flagsCaptor.value
assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
assertThat(distractionFlags).isEqualTo(PackageManager.RESTRICTION_HIDE_NOTIFICATIONS)
assertThat(unactionedPackages).isEmpty()
@@ -75,10 +74,8 @@
PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
verify(pms, never()).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper, never()).sendPackageBroadcast(
- eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), bundleCaptor.capture(),
- anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable(),
- nullable())
+ verify(broadcastHelper, never()).sendDistractingPackagesChanged(
+ any(), any(), any(), any(), any())
assertThat(unactionedPackages).isEmpty()
}
@@ -154,11 +151,11 @@
testHandler.flush()
verify(pms).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED),
- nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(),
- nullable(), nullable(), nullable(), nullable())
- val modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
- val distractionFlags = bundleCaptor.value.getInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS)
+ verify(broadcastHelper).sendDistractingPackagesChanged(
+ any(Computer::class.java), pkgListCaptor.capture(), any(), eq(TEST_USER_ID),
+ flagsCaptor.capture())
+ val modifiedPackages = pkgListCaptor.value
+ val distractionFlags = flagsCaptor.value
assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
assertThat(distractionFlags).isEqualTo(PackageManager.RESTRICTION_NONE)
}
@@ -170,9 +167,8 @@
testHandler.flush()
verify(pms, never()).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper, never()).sendPackageBroadcast(eq(
- Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), nullable(), anyInt(),
- nullable(), nullable(), any(), nullable(), nullable(), nullable(), nullable())
+ verify(broadcastHelper, never()).sendDistractingPackagesChanged(
+ any(), any(), any(), any(), any())
}
@Test
@@ -189,22 +185,21 @@
arrayOfNulls(0), TEST_USER_ID)
testHandler.flush()
verify(pms, never()).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper, never()).sendPackageBroadcast(eq(
- Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), nullable(), anyInt(),
- nullable(), nullable(), any(), nullable(), nullable(), nullable(), nullable())
+ verify(broadcastHelper, never()).sendDistractingPackagesChanged(
+ any(), any(), any(), any(), any())
}
@Test
fun sendDistractingPackagesChanged() {
- distractingPackageHelper.sendDistractingPackagesChanged(packagesToChange, uidsToChange,
- TEST_USER_ID, PackageManager.RESTRICTION_HIDE_NOTIFICATIONS)
+ broadcastHelper.sendDistractingPackagesChanged(pms.snapshotComputer(),
+ packagesToChange, uidsToChange, TEST_USER_ID,
+ PackageManager.RESTRICTION_HIDE_NOTIFICATIONS)
testHandler.flush()
- verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED),
- nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(),
- nullable(), nullable(), nullable(), nullable())
+ verify(broadcastHelper).sendDistractingPackagesChanged(any(Computer::class.java),
+ pkgListCaptor.capture(), uidsCaptor.capture(), eq(TEST_USER_ID), any())
- var changedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
- var changedUids = bundleCaptor.value.getIntArray(Intent.EXTRA_CHANGED_UID_LIST)
+ var changedPackages = pkgListCaptor.value
+ var changedUids = uidsCaptor.value
assertThat(changedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
assertThat(changedUids).asList().containsExactly(
packageSetting1.appId, packageSetting2.appId)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
index 5fd270e..eb00164 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
@@ -17,7 +17,6 @@
package com.android.server.pm
import android.os.Build
-import android.os.Bundle
import android.os.UserHandle
import android.os.UserManager
import com.android.server.pm.pkg.PackageStateInternal
@@ -68,7 +67,11 @@
lateinit var protectedPackages: ProtectedPackages
@Captor
- lateinit var bundleCaptor: ArgumentCaptor<Bundle>
+ lateinit var pkgListCaptor: ArgumentCaptor<Array<String>>
+ @Captor
+ lateinit var flagsCaptor: ArgumentCaptor<Int>
+ @Captor
+ lateinit var uidsCaptor: ArgumentCaptor<IntArray>
@Rule
@JvmField
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
index c5db5db..6c44fd0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
@@ -17,12 +17,12 @@
package com.android.server.pm;
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.content.Intent;
import android.content.pm.PackageInstaller;
@@ -63,9 +63,7 @@
@Before
public void setup() {
- when(mMockSystem.mocks().getInjector().getHandler()).thenReturn(mHandler);
- mPackageMonitorCallbackHelper = new PackageMonitorCallbackHelper(
- mMockSystem.mocks().getInjector());
+ mPackageMonitorCallbackHelper = new PackageMonitorCallbackHelper();
}
@@ -80,7 +78,7 @@
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -93,7 +91,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0}, null /* instantUserIds */,
- null /* broadcastAllowList */);
+ null /* broadcastAllowList */, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any());
@@ -101,7 +99,7 @@
mPackageMonitorCallbackHelper.unregisterPackageMonitorCallback(callback);
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -114,7 +112,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(
@@ -138,7 +136,7 @@
// Notify for user 10
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{10} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -155,7 +153,7 @@
mPackageMonitorCallbackHelper.notifyPackageChanged(FAKE_PACKAGE_NAME,
false /* dontKillApp */, components, FAKE_PACKAGE_UID, null /* reason */,
new int[]{0} /* userIds */, null /* instantUserIds */,
- null /* broadcastAllowList */);
+ null /* broadcastAllowList */, mHandler);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(
@@ -183,7 +181,8 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageAddedForNewUsers(FAKE_PACKAGE_NAME,
FAKE_PACKAGE_UID, new int[]{0} /* userIds */, new int[0], false /* isArchived */,
- PackageInstaller.DATA_LOADER_TYPE_STREAMING, null /* broadcastAllowList */);
+ PackageInstaller.DATA_LOADER_TYPE_STREAMING, null /* broadcastAllowList */,
+ mHandler);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(
@@ -207,7 +206,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyResourcesChanged(true /* mediaStatus */,
true /* replacing */, new String[]{FAKE_PACKAGE_NAME},
- new int[]{FAKE_PACKAGE_UID} /* uids */);
+ new int[]{FAKE_PACKAGE_UID} /* uids */, mHandler);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(
@@ -240,7 +239,7 @@
mPackageMonitorCallbackHelper.onUserRemoved(10);
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{10} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -256,7 +255,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, broadcastAllowList);
+ null /* instantUserIds */, broadcastAllowList, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any());
}
@@ -272,7 +271,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, broadcastAllowList);
+ null /* instantUserIds */, broadcastAllowList, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -288,7 +287,7 @@
Process.SYSTEM_UID);
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, broadcastAllowList);
+ null /* instantUserIds */, broadcastAllowList, mHandler);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any());
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index 6797576..4240373 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -22,12 +22,11 @@
import android.os.PersistableBundle
import com.android.server.testutils.any
import com.android.server.testutils.eq
-import com.android.server.testutils.nullable
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mockito
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -44,17 +43,10 @@
testHandler.flush()
verify(pms).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_PACKAGES_SUSPENDED),
- nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(),
- nullable(), nullable(), nullable(), nullable())
- verify(broadcastHelper).doSendBroadcast(eq(Intent.ACTION_MY_PACKAGE_SUSPENDED), nullable(),
- nullable(), any(), eq(TEST_PACKAGE_1), nullable(), any(), any(), nullable(),
- nullable(), nullable())
- verify(broadcastHelper).doSendBroadcast(eq(Intent.ACTION_MY_PACKAGE_SUSPENDED), nullable(),
- nullable(), any(), eq(TEST_PACKAGE_2), nullable(), any(), any(), nullable(),
- nullable(), nullable())
+ verify(broadcastHelper).sendPackagesSuspendedOrUnsuspendedForUser(any(Computer::class.java),
+ eq(Intent.ACTION_PACKAGES_SUSPENDED), pkgListCaptor.capture(), any(), any(), any())
- var modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
+ var modifiedPackages = pkgListCaptor.value
assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
assertThat(failedNames).isEmpty()
}
@@ -146,6 +138,7 @@
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
+ Mockito.clearInvocations(broadcastHelper)
assertThat(failedNames).isEmpty()
failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
targetPackages, false /* suspended */, null /* appExtras */,
@@ -154,17 +147,13 @@
testHandler.flush()
verify(pms, times(2)).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_PACKAGES_UNSUSPENDED),
- nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(),
- nullable(), nullable(), nullable(), nullable())
- verify(broadcastHelper).doSendBroadcast(eq(Intent.ACTION_MY_PACKAGE_UNSUSPENDED),
- nullable(), nullable(), any(), eq(TEST_PACKAGE_1), nullable(), any(), any(),
- nullable(), nullable(), nullable())
- verify(broadcastHelper).doSendBroadcast(eq(Intent.ACTION_MY_PACKAGE_UNSUSPENDED),
- nullable(), nullable(), any(), eq(TEST_PACKAGE_2), nullable(), any(), any(),
- nullable(), nullable(), nullable())
+ verify(broadcastHelper).sendPackagesSuspendedOrUnsuspendedForUser(any(Computer::class.java),
+ eq(Intent.ACTION_PACKAGES_UNSUSPENDED), pkgListCaptor.capture(), any(), any(),
+ any())
+ verify(broadcastHelper).sendMyPackageSuspendedOrUnsuspended(any(Computer::class.java),
+ any(), any(), any())
- var modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
+ var modifiedPackages = pkgListCaptor.value
assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
assertThat(failedNames).isEmpty()
}
@@ -206,7 +195,7 @@
testHandler.flush()
assertThat(failedNames).isEmpty()
- val result = suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
+ val result = SuspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)!!
assertThat(result.getString(TEST_PACKAGE_1)).isEqualTo(TEST_PACKAGE_1)
@@ -222,14 +211,15 @@
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
+ Mockito.clearInvocations(broadcastHelper)
assertThat(failedNames).isEmpty()
assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE)
assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE)
- assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
+ assertThat(SuspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isNotNull()
- assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
+ assertThat(SuspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNotNull()
suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(),
@@ -238,23 +228,18 @@
testHandler.flush()
verify(pms, times(2)).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
- verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_PACKAGES_UNSUSPENDED),
- nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(),
- nullable(), nullable(), nullable(), nullable())
- verify(broadcastHelper).doSendBroadcast(eq(Intent.ACTION_MY_PACKAGE_UNSUSPENDED),
- nullable(), nullable(), any(), eq(TEST_PACKAGE_1), nullable(), any(), any(),
- nullable(), nullable(), nullable())
- verify(broadcastHelper).doSendBroadcast(eq(Intent.ACTION_MY_PACKAGE_UNSUSPENDED),
- nullable(), nullable(), any(), eq(TEST_PACKAGE_2), nullable(), any(), any(),
- nullable(), nullable(), nullable())
+ verify(broadcastHelper).sendPackagesSuspendedOrUnsuspendedForUser(any(Computer::class.java),
+ eq(Intent.ACTION_PACKAGES_UNSUSPENDED), any(), any(), any(), any())
+ verify(broadcastHelper).sendMyPackageSuspendedOrUnsuspended(any(Computer::class.java),
+ any(), any(), any())
assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isNull()
assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNull()
- assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
+ assertThat(SuspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isNull()
- assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
+ assertThat(SuspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(),
TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNull()
}
@@ -319,39 +304,4 @@
assertThat(result.title).isEqualTo(TEST_PACKAGE_1)
}
-
- @Test
- @Throws(Exception::class)
- fun sendPackagesSuspendedForUser() {
- suspendPackageHelper.sendPackagesSuspendedForUser(
- Intent.ACTION_PACKAGES_SUSPENDED, packagesToChange, uidsToChange, false, TEST_USER_ID)
- testHandler.flush()
- verify(broadcastHelper).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(),
- anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable(),
- nullable())
-
- var changedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
- var changedUids = bundleCaptor.value.getIntArray(Intent.EXTRA_CHANGED_UID_LIST)
- assertThat(changedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
- assertThat(changedUids).asList().containsExactly(
- packageSetting1.appId, packageSetting2.appId)
- }
-
- @Test
- @Throws(Exception::class)
- fun sendPackagesSuspendModifiedForUser() {
- suspendPackageHelper.sendPackagesSuspendedForUser(
- Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, packagesToChange, uidsToChange, false, TEST_USER_ID)
- testHandler.flush()
- verify(broadcastHelper).sendPackageBroadcast(
- eq(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED), nullable(), bundleCaptor.capture(),
- anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable(),
- nullable())
-
- var modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST)
- var modifiedUids = bundleCaptor.value.getIntArray(Intent.EXTRA_CHANGED_UID_LIST)
- assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2)
- assertThat(modifiedUids).asList().containsExactly(
- packageSetting1.appId, packageSetting2.appId)
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 82b7540..2f0257a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -39,11 +39,16 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.testing.DexmakerShareClassLoaderRule;
import android.view.Display;
+import android.view.WindowManager;
import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.test.MessageCapturingHandler;
@@ -76,6 +81,9 @@
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
AccessibilityServiceConnection mConnection;
@Mock AccessibilityUserState mMockUserState;
@@ -113,6 +121,8 @@
when(mMockIBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient);
when(mMockA11yTrace.isA11yTracingEnabled()).thenReturn(false);
+ when(mMockContext.getSystemService(Context.DISPLAY_SERVICE))
+ .thenReturn(new DisplayManager(mMockContext));
mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(),
@@ -168,6 +178,18 @@
assertFalse(mConnection.getServiceInfo().crashed);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ADD_WINDOW_TOKEN_WITHOUT_LOCK)
+ public void onServiceConnected_addsWindowTokens() {
+ setServiceBinding(COMPONENT_NAME);
+ mConnection.bindLocked();
+ mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder);
+
+ verify(mMockWindowManagerInternal).addWindowToken(
+ any(), eq(WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY),
+ anyInt(), eq(null));
+ }
+
private void setServiceBinding(ComponentName componentName) {
when(mMockUserState.getBindingServicesLocked())
.thenReturn(new HashSet<>(Arrays.asList(componentName)));
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index b4558b2..63281b7 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -35,6 +35,7 @@
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -46,6 +47,9 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.testing.DexmakerShareClassLoaderRule;
@@ -88,6 +92,9 @@
@Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Mock private AccessibilityServiceInfo mMockServiceInfo;
@Mock private AccessibilityServiceConnection mMockConnection;
@@ -188,7 +195,7 @@
mUserState.addServiceLocked(mMockConnection);
- verify(mMockConnection, never()).onAdded();
+ verify(mMockListener, never()).onServiceInfoChangedLocked(any());
}
@Test
@@ -197,13 +204,24 @@
mUserState.addServiceLocked(mMockConnection);
- verify(mMockConnection).onAdded();
assertTrue(mUserState.getBoundServicesLocked().contains(mMockConnection));
assertEquals(mMockConnection, mUserState.mComponentNameToServiceMap.get(COMPONENT_NAME));
verify(mMockListener).onServiceInfoChangedLocked(eq(mUserState));
}
@Test
+ // addServiceLocked only calls addWindowTokensForAllDisplays when
+ // FLAG_ADD_WINDOW_TOKEN_WITHOUT_LOCK is off, so skip the test if it is on.
+ @RequiresFlagsDisabled(Flags.FLAG_ADD_WINDOW_TOKEN_WITHOUT_LOCK)
+ public void addService_flagDisabled_addsWindowTokens() {
+ when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
+
+ mUserState.addServiceLocked(mMockConnection);
+
+ verify(mMockConnection).addWindowTokensForAllDisplays();
+ }
+
+ @Test
public void reconcileSoftKeyboardMode_whenStateNotMatchSettings_setBothDefault() {
// When soft kb show mode is hidden in settings and is auto in state.
putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
index 4ce9ba0..3ee5f61 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -21,8 +21,11 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -36,6 +39,10 @@
import android.content.pm.ServiceInfo;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import com.android.server.accessibility.test.MessageCapturingHandler;
@@ -43,6 +50,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -58,6 +66,9 @@
MessageCapturingHandler mMessageCapturingHandler;
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Mock Context mMockContext;
@Mock AccessibilityServiceInfo mMockServiceInfo;
@Mock ResolveInfo mMockResolveInfo;
@@ -197,6 +208,24 @@
assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked());
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ADD_WINDOW_TOKEN_WITHOUT_LOCK)
+ public void registerUiAutomationService_callsAddWindowTokenUsingHandler() {
+ register(0);
+ // registerUiTestAutomationServiceLocked() should not directly call addWindowToken.
+ verify(mMockWindowManagerInternal, never()).addWindowToken(
+ any(), anyInt(), anyInt(), any());
+
+ // Advance UiAutomationManager#UiAutomationService's handler.
+ mMessageCapturingHandler.sendAllMessages();
+
+ // After advancing the handler we expect addWindowToken to have been called
+ // by the UiAutomationService instance.
+ verify(mMockWindowManagerInternal).addWindowToken(
+ any(), eq(WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY),
+ anyInt(), eq(null));
+ }
+
private void register(int flags) {
mUiAutomationManager.registerUiTestAutomationServiceLocked(mMockOwner,
mMockAccessibilityServiceClient, mMockContext, mMockServiceInfo, SERVICE_ID,