diff options
226 files changed, 7104 insertions, 6572 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java index 66767e21a2e7..da429af7e351 100644 --- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java +++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java @@ -210,6 +210,8 @@ public class AlarmManager { * on how frequently it can be scheduled. Only available (and automatically applied) to * system alarms. * + * <p>Note that alarms set with a {@link WorkSource} <b>do not</b> get this flag. + * * @hide */ @UnsupportedAppUsage diff --git a/core/api/current.txt b/core/api/current.txt index ec87591918bd..c80c4cb15050 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -113,8 +113,9 @@ package android { field public static final String MANAGE_MEDIA = "android.permission.MANAGE_MEDIA"; field public static final String MANAGE_ONGOING_CALLS = "android.permission.MANAGE_ONGOING_CALLS"; field public static final String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS"; - field public static final String MANAGE_WIFI_AUTO_JOIN = "android.permission.MANAGE_WIFI_AUTO_JOIN"; + field @Deprecated public static final String MANAGE_WIFI_AUTO_JOIN = "android.permission.MANAGE_WIFI_AUTO_JOIN"; field public static final String MANAGE_WIFI_INTERFACES = "android.permission.MANAGE_WIFI_INTERFACES"; + field public static final String MANAGE_WIFI_NETWORK_SELECTION = "android.permission.MANAGE_WIFI_NETWORK_SELECTION"; field public static final String MASTER_CLEAR = "android.permission.MASTER_CLEAR"; field public static final String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL"; field public static final String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS"; @@ -3335,7 +3336,7 @@ package android.accessibilityservice { } public class InputMethod { - ctor protected InputMethod(@NonNull android.accessibilityservice.AccessibilityService); + ctor public InputMethod(@NonNull android.accessibilityservice.AccessibilityService); method @Nullable public final android.accessibilityservice.InputMethod.AccessibilityInputConnection getCurrentInputConnection(); method @Nullable public final android.view.inputmethod.EditorInfo getCurrentInputEditorInfo(); method public final boolean getCurrentInputStarted(); @@ -4275,7 +4276,6 @@ package android.app { method public void setLocusContext(@Nullable android.content.LocusId, @Nullable android.os.Bundle); method public final void setMediaController(android.media.session.MediaController); method public void setPictureInPictureParams(@NonNull android.app.PictureInPictureParams); - method public void setPreferDockBigOverlays(boolean); method @Deprecated public final void setProgress(int); method @Deprecated public final void setProgressBarIndeterminate(boolean); method @Deprecated public final void setProgressBarIndeterminateVisibility(boolean); @@ -4285,6 +4285,7 @@ package android.app { method public final void setResult(int); method public final void setResult(int, android.content.Intent); method @Deprecated public final void setSecondaryProgress(int); + method public void setShouldDockBigOverlays(boolean); method public void setShowWhenLocked(boolean); method public void setTaskDescription(android.app.ActivityManager.TaskDescription); method public void setTitle(CharSequence); @@ -4295,6 +4296,7 @@ package android.app { method public void setVisible(boolean); method public final void setVolumeControlStream(int); method public void setVrModeEnabled(boolean, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException; + method public boolean shouldDockBigOverlays(); method public boolean shouldShowRequestPermissionRationale(@NonNull String); method public boolean shouldUpRecreateTask(android.content.Intent); method public boolean showAssist(android.os.Bundle); @@ -26063,11 +26065,9 @@ package android.media.tv.interactive { public static final class AppLinkInfo.Builder { ctor public AppLinkInfo.Builder(@NonNull String, @NonNull String); method @NonNull public android.media.tv.interactive.AppLinkInfo build(); - method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setClassName(@NonNull String); - method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setPackageName(@NonNull String); - method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriHost(@Nullable String); - method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriPrefix(@Nullable String); - method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriScheme(@Nullable String); + method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriHost(@NonNull String); + method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriPrefix(@NonNull String); + method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriScheme(@NonNull String); } public final class TvInteractiveAppInfo implements android.os.Parcelable { diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 241e5c8d97c4..7aef9a6b767a 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -102,6 +102,7 @@ package android.content.pm { public abstract class PackageManager { method @NonNull public String getPermissionControllerPackageName(); method @NonNull public String getSdkSandboxPackageName(); + field public static final String EXTRA_VERIFICATION_ROOT_HASH = "android.content.pm.extra.VERIFICATION_ROOT_HASH"; field public static final int MATCH_STATIC_SHARED_AND_SDK_LIBRARIES = 67108864; // 0x4000000 } @@ -454,6 +455,14 @@ package android.provider { } +package android.telecom { + + public abstract class ConnectionService extends android.app.Service { + method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.Connection onCreateUnknownConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); + } + +} + package android.telephony { public abstract class CellSignalStrength { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 229fd6068721..5f2dcb39007c 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -469,7 +469,6 @@ package android.app { method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions); method @Deprecated public boolean isBackgroundVisibleBehind(); method @Deprecated public void onBackgroundVisibleBehindChanged(boolean); - method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void startActivityAsUser(@NonNull android.content.Intent, @Nullable android.os.Bundle, @NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void startActivityForResultAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void startActivityForResultAsUser(@NonNull android.content.Intent, int, @Nullable android.os.Bundle, @NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void startActivityForResultAsUser(@NonNull android.content.Intent, @NonNull String, int, @Nullable android.os.Bundle, @NonNull android.os.UserHandle); @@ -1704,6 +1703,7 @@ package android.app.cloudsearch { field public static final String EXTRAINFO_ACTION_BUTTON_IMAGE_PREREGISTERING = "android.app.cloudsearch.ACTION_BUTTON_IMAGE"; field public static final String EXTRAINFO_ACTION_BUTTON_TEXT_PREREGISTERING = "android.app.cloudsearch.ACTION_BUTTON_TEXT"; field public static final String EXTRAINFO_APP_BADGES = "android.app.cloudsearch.APP_BADGES"; + field public static final String EXTRAINFO_APP_CARD_ACTION = "android.app.cloudsearch.APP_CARD_ACTION"; field public static final String EXTRAINFO_APP_CONTAINS_ADS_DISCLAIMER = "android.app.cloudsearch.APP_CONTAINS_ADS_DISCLAIMER"; field public static final String EXTRAINFO_APP_CONTAINS_IAP_DISCLAIMER = "android.app.cloudsearch.APP_CONTAINS_IAP_DISCLAIMER"; field public static final String EXTRAINFO_APP_DEVELOPER_NAME = "android.app.cloudsearch.APP_DEVELOPER_NAME"; @@ -1713,6 +1713,7 @@ package android.app.cloudsearch { field public static final String EXTRAINFO_APP_REVIEW_COUNT = "android.app.cloudsearch.APP_REVIEW_COUNT"; field public static final String EXTRAINFO_APP_SIZE_BYTES = "android.app.cloudsearch.APP_SIZE_BYTES"; field public static final String EXTRAINFO_APP_STAR_RATING = "android.app.cloudsearch.APP_STAR_RATING"; + field public static final String EXTRAINFO_INSTALL_BUTTON_ACTION = "android.app.cloudsearch.INSTALL_BUTTON_ACTION"; field public static final String EXTRAINFO_LONG_DESCRIPTION = "android.app.cloudsearch.LONG_DESCRIPTION"; field public static final String EXTRAINFO_SCREENSHOTS = "android.app.cloudsearch.SCREENSHOTS"; field public static final String EXTRAINFO_SHORT_DESCRIPTION = "android.app.cloudsearch.SHORT_DESCRIPTION"; @@ -2948,6 +2949,7 @@ package android.content { method public void sendBroadcastMultiplePermissions(@NonNull android.content.Intent, @NonNull String[], @Nullable android.app.BroadcastOptions); method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle); + method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @Nullable android.os.Bundle, @NonNull android.os.UserHandle); field public static final String AMBIENT_CONTEXT_SERVICE = "ambient_context"; field public static final String APP_HIBERNATION_SERVICE = "app_hibernation"; field public static final String APP_INTEGRITY_SERVICE = "app_integrity"; @@ -6946,7 +6948,7 @@ package android.media.tv.tuner { } public class Lnb implements java.lang.AutoCloseable { - method public void addCallback(@NonNull android.media.tv.tuner.LnbCallback, @NonNull java.util.concurrent.Executor); + method public void addCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback); method public void close(); method public boolean removeCallback(@NonNull android.media.tv.tuner.LnbCallback); method public int sendDiseqcMessage(@NonNull byte[]); @@ -9820,7 +9822,7 @@ package android.os { method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isAdminUser(); method public boolean isCloneProfile(); - method public boolean isCredentialSharedWithParent(); + method public boolean isCredentialSharableWithParent(); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isGuestUser(); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isMediaSharedWithParent(); @@ -10581,7 +10583,6 @@ package android.provider { field public static final String AUTO_REVOKE_DISABLED = "auto_revoke_disabled"; field public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category."; field public static final String DOZE_ALWAYS_ON = "doze_always_on"; - field public static final String FAST_PAIR_SCAN_ENABLED = "fast_pair_scan_enabled"; field public static final String HUSH_GESTURE_USED = "hush_gesture_used"; field public static final String INSTANT_APPS_ENABLED = "instant_apps_enabled"; field public static final String LAST_SETUP_SHOWN = "last_setup_shown"; @@ -12218,7 +12219,6 @@ package android.telecom { public abstract class ConnectionService extends android.app.Service { method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference); - method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.Connection onCreateUnknownConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); } public abstract class InCallService extends android.app.Service { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 5aec193f33d4..2eb0f194887f 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -422,9 +422,9 @@ package android.app { method @NonNull public android.content.res.Configuration getConfiguration(); method public int getParentTaskId(); method @Nullable public android.app.PictureInPictureParams getPictureInPictureParams(); - method public boolean getPreferDockBigOverlays(); method @NonNull public android.window.WindowContainerToken getToken(); method public boolean hasParentTask(); + method public boolean shouldDockBigOverlays(); } public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener { diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index c82f5f6d54fc..3cb04e710d3b 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -825,17 +825,7 @@ public abstract class AccessibilityService extends Service { for (int i = 0; i < mMagnificationControllers.size(); i++) { mMagnificationControllers.valueAt(i).onServiceConnectedLocked(); } - AccessibilityServiceInfo info = getServiceInfo(); - if (info != null) { - boolean requestIme = (info.flags - & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0; - if (requestIme && !mInputMethodInitialized) { - mInputMethod = onCreateInputMethod(); - mInputMethodInitialized = true; - } - } else { - Log.e(LOG_TAG, "AccessibilityServiceInfo is null in dispatchServiceConnected"); - } + updateInputMethod(getServiceInfo()); } if (mSoftKeyboardController != null) { mSoftKeyboardController.onServiceConnected(); @@ -846,6 +836,20 @@ public abstract class AccessibilityService extends Service { onServiceConnected(); } + private void updateInputMethod(AccessibilityServiceInfo info) { + if (info != null) { + boolean requestIme = (info.flags + & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0; + if (requestIme && !mInputMethodInitialized) { + mInputMethod = onCreateInputMethod(); + mInputMethodInitialized = true; + } else if (!requestIme & mInputMethodInitialized) { + mInputMethod = null; + mInputMethodInitialized = false; + } + } + } + /** * This method is a part of the {@link AccessibilityService} lifecycle and is * called after the system has successfully bound to the service. If is @@ -2521,6 +2525,7 @@ public abstract class AccessibilityService extends Service { */ public final void setServiceInfo(AccessibilityServiceInfo info) { mInfo = info; + updateInputMethod(info); sendServiceInfo(); } diff --git a/core/java/android/accessibilityservice/InputMethod.java b/core/java/android/accessibilityservice/InputMethod.java index 001d804b22d6..36cfd0e4341e 100644 --- a/core/java/android/accessibilityservice/InputMethod.java +++ b/core/java/android/accessibilityservice/InputMethod.java @@ -67,7 +67,7 @@ public class InputMethod { private InputConnection mStartedInputConnection; private EditorInfo mInputEditorInfo; - protected InputMethod(@NonNull AccessibilityService service) { + public InputMethod(@NonNull AccessibilityService service) { mService = service; } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 8f348a4e81d6..ec9bb264835e 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -984,6 +984,8 @@ public class Activity extends ContextThemeWrapper private boolean mIsInMultiWindowMode; private boolean mIsInPictureInPictureMode; + private boolean mShouldDockBigOverlays; + private UiTranslationController mUiTranslationController; private SplashScreen mSplashScreen; @@ -2977,13 +2979,28 @@ public class Activity extends ContextThemeWrapper * <p> If specified, the system will try to respect the preference, but it may be * overridden by a user preference. * - * @param preferDockBigOverlays indicates that the activity prefers big overlays to be - * docked next to it instead of overlaying its content + * @param shouldDockBigOverlays indicates that big overlays should be docked next to the + * activity instead of overlay its content * * @see PictureInPictureParams.Builder#setExpandedAspectRatio + * @see #shouldDockBigOverlays + */ + public void setShouldDockBigOverlays(boolean shouldDockBigOverlays) { + ActivityClient.getInstance().setShouldDockBigOverlays(mToken, shouldDockBigOverlays); + mShouldDockBigOverlays = shouldDockBigOverlays; + } + + /** + * Returns whether big overlays should be docked next to the activity as set by + * {@link #setShouldDockBigOverlays}. + * + * @return {@code true} if big overlays should be docked next to the activity instead + * of overlay its content + * + * @see #setShouldDockBigOverlays */ - public void setPreferDockBigOverlays(boolean preferDockBigOverlays) { - ActivityClient.getInstance().setPreferDockBigOverlays(mToken, preferDockBigOverlays); + public boolean shouldDockBigOverlays() { + return mShouldDockBigOverlays; } void dispatchMovedToDisplay(int displayId, Configuration config) { @@ -5663,7 +5680,6 @@ public class Activity extends ContextThemeWrapper * @throws ActivityNotFoundException * @hide */ - @SystemApi @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) public void startActivityAsUser(@NonNull Intent intent, @Nullable Bundle options, @NonNull UserHandle user) { @@ -8249,6 +8265,7 @@ public class Activity extends ContextThemeWrapper .getWindowingMode(); mIsInMultiWindowMode = inMultiWindowMode(windowingMode); mIsInPictureInPictureMode = windowingMode == WINDOWING_MODE_PINNED; + mShouldDockBigOverlays = getResources().getBoolean(R.bool.config_dockBigOverlayWindows); restoreHasCurrentPermissionRequest(icicle); if (persistentState != null) { onCreate(icicle, persistentState); diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index cf8480c6b9c8..7b7b1efdb86b 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -324,9 +324,9 @@ public class ActivityClient { } } - void setPreferDockBigOverlays(IBinder token, boolean preferDockBigOverlays) { + void setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays) { try { - getActivityClientController().setPreferDockBigOverlays(token, preferDockBigOverlays); + getActivityClientController().setShouldDockBigOverlays(token, shouldDockBigOverlays); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 64f0301fab22..b1a4e4148eec 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3587,7 +3587,7 @@ public final class ActivityThread extends ClientTransactionHandler } try { - Application app = r.packageInfo.makeApplication(false, mInstrumentation); + Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( @@ -4286,7 +4286,7 @@ public final class ActivityThread extends ClientTransactionHandler BroadcastReceiver receiver; ContextImpl context; try { - app = packageInfo.makeApplication(false, mInstrumentation); + app = packageInfo.makeApplicationInner(false, mInstrumentation); context = (ContextImpl) app.getBaseContext(); if (data.info.splitName != null) { context = (ContextImpl) context.createContextForSplit(data.info.splitName); @@ -4475,7 +4475,7 @@ public final class ActivityThread extends ClientTransactionHandler try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); - Application app = packageInfo.makeApplication(false, mInstrumentation); + Application app = packageInfo.makeApplicationInner(false, mInstrumentation); final java.lang.ClassLoader cl; if (data.info.splitName != null) { @@ -6695,7 +6695,7 @@ public final class ActivityThread extends ClientTransactionHandler try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. - app = data.info.makeApplication(data.restrictedBackupMode, null); + app = data.info.makeApplicationInner(data.restrictedBackupMode, null); // Propagate autofill compat state app.setAutofillOptions(data.autofillOptions); @@ -7565,7 +7565,7 @@ public final class ActivityThread extends ClientTransactionHandler mInstrumentation.basicInit(this); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); - mInitialApplication = context.mPackageInfo.makeApplication(true, null); + mInitialApplication = context.mPackageInfo.makeApplicationInner(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index caf1c41b7622..130716122ed2 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -88,7 +88,7 @@ interface IActivityClientController { boolean enterPictureInPictureMode(in IBinder token, in PictureInPictureParams params); void setPictureInPictureParams(in IBinder token, in PictureInPictureParams params); - oneway void setPreferDockBigOverlays(in IBinder token, in boolean preferDockBigOverlays); + oneway void setShouldDockBigOverlays(in IBinder token, in boolean shouldDockBigOverlays); void toggleFreeformWindowingMode(in IBinder token); oneway void startLockTaskModeByToken(in IBinder token); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index cf259e577a5a..d35c5bebd301 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -1352,9 +1352,28 @@ public final class LoadedApk { return mResources; } + /** + * This is for 3p apps accessing this hidden API directly... in which case, we don't return + * the cached Application instance. + */ @UnsupportedAppUsage public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { + return makeApplicationInner(forceDefaultAppClass, instrumentation, + /* allowDuplicateInstances= */ true); + } + + /** + * This is for all the (internal) callers, for which we do return the cached instance. + */ + public Application makeApplicationInner(boolean forceDefaultAppClass, + Instrumentation instrumentation) { + return makeApplicationInner(forceDefaultAppClass, instrumentation, + /* allowDuplicateInstances= */ false); + } + + private Application makeApplicationInner(boolean forceDefaultAppClass, + Instrumentation instrumentation, boolean allowDuplicateInstances) { if (mApplication != null) { return mApplication; } @@ -1366,11 +1385,15 @@ public final class LoadedApk { // Looks like this is always happening for the system server, because // the LoadedApk created in systemMain() -> attach() isn't cached properly? if (!"android".equals(mPackageName)) { - Slog.wtf(TAG, "App instance already created for package=" + mPackageName + Slog.wtfStack(TAG, "App instance already created for package=" + mPackageName + " instance=" + cached); } - mApplication = cached; - return cached; + if (!allowDuplicateInstances) { + mApplication = cached; + return cached; + } + // Some apps intentionally call makeApplication() to create a new Application + // instance... Sigh... } } @@ -1421,8 +1444,10 @@ public final class LoadedApk { } mActivityThread.mAllApplications.add(app); mApplication = app; - synchronized (sApplications) { - sApplications.put(mPackageName, app); + if (!allowDuplicateInstances) { + synchronized (sApplications) { + sApplications.put(mPackageName, app); + } } if (instrumentation != null) { diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 5c7c73c2d683..1a38fcfba5a0 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -188,7 +188,7 @@ public class TaskInfo { /** * @hide */ - public boolean preferDockBigOverlays; + public boolean shouldDockBigOverlays; /** * The task id of the host Task of the launch-into-pip Activity, i.e., it points to the Task @@ -392,8 +392,8 @@ public class TaskInfo { /** @hide */ @TestApi - public boolean getPreferDockBigOverlays() { - return preferDockBigOverlays; + public boolean shouldDockBigOverlays() { + return shouldDockBigOverlays; } /** @hide */ @@ -465,7 +465,7 @@ public class TaskInfo { && displayAreaFeatureId == that.displayAreaFeatureId && Objects.equals(positionInParent, that.positionInParent) && Objects.equals(pictureInPictureParams, that.pictureInPictureParams) - && Objects.equals(preferDockBigOverlays, that.preferDockBigOverlays) + && Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays) && Objects.equals(displayCutoutInsets, that.displayCutoutInsets) && getWindowingMode() == that.getWindowingMode() && Objects.equals(taskDescription, that.taskDescription) @@ -522,7 +522,7 @@ public class TaskInfo { token = WindowContainerToken.CREATOR.createFromParcel(source); topActivityType = source.readInt(); pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR); - preferDockBigOverlays = source.readBoolean(); + shouldDockBigOverlays = source.readBoolean(); launchIntoPipHostTaskId = source.readInt(); displayCutoutInsets = source.readTypedObject(Rect.CREATOR); topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR); @@ -569,7 +569,7 @@ public class TaskInfo { token.writeToParcel(dest, flags); dest.writeInt(topActivityType); dest.writeTypedObject(pictureInPictureParams, flags); - dest.writeBoolean(preferDockBigOverlays); + dest.writeBoolean(shouldDockBigOverlays); dest.writeInt(launchIntoPipHostTaskId); dest.writeTypedObject(displayCutoutInsets, flags); dest.writeTypedObject(topActivityInfo, flags); @@ -610,7 +610,7 @@ public class TaskInfo { + " token=" + token + " topActivityType=" + topActivityType + " pictureInPictureParams=" + pictureInPictureParams - + " preferDockBigOverlays=" + preferDockBigOverlays + + " shouldDockBigOverlays=" + shouldDockBigOverlays + " launchIntoPipHostTaskId=" + launchIntoPipHostTaskId + " displayCutoutSafeInsets=" + displayCutoutInsets + " topActivityInfo=" + topActivityInfo diff --git a/core/java/android/app/cloudsearch/SearchResult.java b/core/java/android/app/cloudsearch/SearchResult.java index af8adacd4258..1ca01d4afe61 100644 --- a/core/java/android/app/cloudsearch/SearchResult.java +++ b/core/java/android/app/cloudsearch/SearchResult.java @@ -71,6 +71,8 @@ public final class SearchResult implements Parcelable { EXTRAINFO_APP_BADGES, EXTRAINFO_ACTION_BUTTON_TEXT_PREREGISTERING, EXTRAINFO_ACTION_BUTTON_IMAGE_PREREGISTERING, + EXTRAINFO_APP_CARD_ACTION, + EXTRAINFO_INSTALL_BUTTON_ACTION, EXTRAINFO_WEB_URL, EXTRAINFO_WEB_ICON}) public @interface SearchResultExtraInfoKey {} @@ -119,6 +121,14 @@ public final class SearchResult implements Parcelable { @SuppressLint("IntentName") public static final String EXTRAINFO_ACTION_BUTTON_IMAGE_PREREGISTERING = "android.app.cloudsearch.ACTION_BUTTON_IMAGE"; + /** Intent for tapping the app card, PendingIntent expected. */ + @SuppressLint("IntentName") + public static final String EXTRAINFO_APP_CARD_ACTION = + "android.app.cloudsearch.APP_CARD_ACTION"; + /** Intent for tapping the install button, PendingIntent expected. */ + @SuppressLint("IntentName") + public static final String EXTRAINFO_INSTALL_BUTTON_ACTION = + "android.app.cloudsearch.INSTALL_BUTTON_ACTION"; /** Web content's URL, String value expected. */ public static final String EXTRAINFO_WEB_URL = "android.app.cloudsearch.WEB_URL"; /** Web content's domain icon, android.graphics.drawable.Icon expected. */ diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java index 41b1a1feae80..cbb51838507b 100644 --- a/core/java/android/companion/virtual/VirtualDeviceParams.java +++ b/core/java/android/companion/virtual/VirtualDeviceParams.java @@ -28,6 +28,8 @@ import android.os.Parcelable; import android.os.UserHandle; import android.util.ArraySet; +import com.android.internal.util.Preconditions; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -82,7 +84,7 @@ public final class VirtualDeviceParams implements Parcelable { public static final int ACTIVITY_POLICY_DEFAULT_BLOCKED = 1; private final int mLockState; - private final ArraySet<UserHandle> mUsersWithMatchingAccounts; + @NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts; @NonNull private final ArraySet<ComponentName> mAllowedActivities; @NonNull private final ArraySet<ComponentName> mBlockedActivities; @ActivityPolicy @@ -94,10 +96,14 @@ public final class VirtualDeviceParams implements Parcelable { @NonNull Set<ComponentName> allowedActivities, @NonNull Set<ComponentName> blockedActivities, @ActivityPolicy int defaultActivityPolicy) { + Preconditions.checkNotNull(usersWithMatchingAccounts); + Preconditions.checkNotNull(allowedActivities); + Preconditions.checkNotNull(blockedActivities); + mLockState = lockState; mUsersWithMatchingAccounts = new ArraySet<>(usersWithMatchingAccounts); - mAllowedActivities = allowedActivities == null ? null : new ArraySet<>(allowedActivities); - mBlockedActivities = blockedActivities == null ? null : new ArraySet<>(blockedActivities); + mAllowedActivities = new ArraySet<>(allowedActivities); + mBlockedActivities = new ArraySet<>(blockedActivities); mDefaultActivityPolicy = defaultActivityPolicy; } @@ -130,30 +136,24 @@ public final class VirtualDeviceParams implements Parcelable { } /** - * Returns the set of activities allowed to be streamed, or {@code null} if all activities are + * Returns the set of activities allowed to be streamed, or empty set if all activities are * allowed, except the ones explicitly blocked. * * @see Builder#setAllowedActivities(Set) */ @NonNull public Set<ComponentName> getAllowedActivities() { - if (mAllowedActivities == null) { - return Collections.emptySet(); - } return Collections.unmodifiableSet(mAllowedActivities); } /** - * Returns the set of activities that are blocked from streaming, or {@code null} to indicate + * Returns the set of activities that are blocked from streaming, or empty set to indicate * that all activities in {@link #getAllowedActivities} are allowed. * * @see Builder#setBlockedActivities(Set) */ @NonNull public Set<ComponentName> getBlockedActivities() { - if (mBlockedActivities == null) { - return Collections.emptySet(); - } return Collections.unmodifiableSet(mBlockedActivities); } @@ -237,7 +237,7 @@ public final class VirtualDeviceParams implements Parcelable { public static final class Builder { private @LockState int mLockState = LOCK_STATE_DEFAULT; - private Set<UserHandle> mUsersWithMatchingAccounts; + @NonNull private Set<UserHandle> mUsersWithMatchingAccounts = Collections.emptySet();; @NonNull private Set<ComponentName> mBlockedActivities = Collections.emptySet(); @NonNull private Set<ComponentName> mAllowedActivities = Collections.emptySet(); @ActivityPolicy @@ -282,6 +282,7 @@ public final class VirtualDeviceParams implements Parcelable { @NonNull public Builder setUsersWithMatchingAccounts( @NonNull Set<UserHandle> usersWithMatchingAccounts) { + Preconditions.checkNotNull(usersWithMatchingAccounts); mUsersWithMatchingAccounts = usersWithMatchingAccounts; return this; } @@ -301,6 +302,7 @@ public final class VirtualDeviceParams implements Parcelable { */ @NonNull public Builder setAllowedActivities(@NonNull Set<ComponentName> allowedActivities) { + Preconditions.checkNotNull(allowedActivities); if (mDefaultActivityPolicyConfigured && mDefaultActivityPolicy != ACTIVITY_POLICY_DEFAULT_BLOCKED) { throw new IllegalArgumentException( @@ -327,6 +329,7 @@ public final class VirtualDeviceParams implements Parcelable { */ @NonNull public Builder setBlockedActivities(@NonNull Set<ComponentName> blockedActivities) { + Preconditions.checkNotNull(blockedActivities); if (mDefaultActivityPolicyConfigured && mDefaultActivityPolicy != ACTIVITY_POLICY_DEFAULT_ALLOWED) { throw new IllegalArgumentException( @@ -343,9 +346,6 @@ public final class VirtualDeviceParams implements Parcelable { */ @NonNull public VirtualDeviceParams build() { - if (mUsersWithMatchingAccounts == null) { - mUsersWithMatchingAccounts = Collections.emptySet(); - } return new VirtualDeviceParams( mLockState, mUsersWithMatchingAccounts, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 2bda020192d5..60efb4d3ec81 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2011,9 +2011,9 @@ public abstract class Context { * @hide */ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) - @UnsupportedAppUsage - public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options, - UserHandle userId) { + @SystemApi + public void startActivityAsUser(@RequiresPermission @NonNull Intent intent, + @Nullable Bundle options, @NonNull UserHandle userId) { throw new RuntimeException("Not implemented. Must override in a subclass."); } diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java index 410e106ce584..148eacc0c4d4 100644 --- a/core/java/android/content/pm/PackageInfoLite.java +++ b/core/java/android/content/pm/PackageInfoLite.java @@ -79,6 +79,11 @@ public class PackageInfoLite implements Parcelable { public boolean debuggable; /** + * Indicates if this apk is a sdk. + */ + public boolean isSdkLibrary; + + /** * Specifies the recommended install location. Can be one of * {@link InstallLocationUtils#RECOMMEND_INSTALL_INTERNAL} to install on internal storage, * {@link InstallLocationUtils#RECOMMEND_INSTALL_EXTERNAL} to install on external media, diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 78dddb577c36..f9beaa7cd0e9 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4262,8 +4262,9 @@ public abstract class PackageManager { * for more details. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final String EXTRA_VERIFICATION_ROOT_HASH = - "android.content.pm.extra.EXTRA_VERIFICATION_ROOT_HASH"; + "android.content.pm.extra.VERIFICATION_ROOT_HASH"; /** * Extra field name for the ID of a intent filter pending verification. diff --git a/core/java/android/content/pm/parsing/ApkLite.java b/core/java/android/content/pm/parsing/ApkLite.java index 5ffb958082fb..269bec256282 100644 --- a/core/java/android/content/pm/parsing/ApkLite.java +++ b/core/java/android/content/pm/parsing/ApkLite.java @@ -133,6 +133,11 @@ public class ApkLite { */ private final boolean mHasDeviceAdminReceiver; + /** + * Indicates if this apk is a sdk. + */ + private final boolean mIsSdkLibrary; + public ApkLite(String path, String packageName, String splitName, boolean isFeatureSplit, String configForSplit, String usesSplitName, boolean isSplitRequired, int versionCode, int versionCodeMajor, int revisionCode, int installLocation, @@ -143,7 +148,7 @@ public class ApkLite { String requiredSystemPropertyName, String requiredSystemPropertyValue, int minSdkVersion, int targetSdkVersion, int rollbackDataPolicy, Set<String> requiredSplitTypes, Set<String> splitTypes, - boolean hasDeviceAdminReceiver) { + boolean hasDeviceAdminReceiver, boolean isSdkLibrary) { mPath = path; mPackageName = packageName; mSplitName = splitName; @@ -176,6 +181,7 @@ public class ApkLite { mTargetSdkVersion = targetSdkVersion; mRollbackDataPolicy = rollbackDataPolicy; mHasDeviceAdminReceiver = hasDeviceAdminReceiver; + mIsSdkLibrary = isSdkLibrary; } /** @@ -473,11 +479,19 @@ public class ApkLite { return mHasDeviceAdminReceiver; } + /** + * Indicates if this apk is a sdk. + */ + @DataClass.Generated.Member + public boolean isIsSdkLibrary() { + return mIsSdkLibrary; + } + @DataClass.Generated( - time = 1635266936769L, + time = 1643063342990L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ApkLite.java", - inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final int mRollbackDataPolicy\nprivate final boolean mHasDeviceAdminReceiver\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)") + inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final int mRollbackDataPolicy\nprivate final boolean mHasDeviceAdminReceiver\nprivate final boolean mIsSdkLibrary\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)") @Deprecated private void __metadata() {} diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 165cae826187..5680bcd2e2e6 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -87,6 +87,7 @@ public class ApkLiteParseUtils { private static final String TAG_USES_SDK = "uses-sdk"; private static final String TAG_USES_SPLIT = "uses-split"; private static final String TAG_MANIFEST = "manifest"; + private static final String TAG_SDK_LIBRARY = "sdk-library"; private static final int SDK_VERSION = Build.VERSION.SDK_INT; private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; @@ -449,6 +450,8 @@ public class ApkLiteParseUtils { boolean hasDeviceAdminReceiver = false; + boolean isSdkLibrary = false; + // Only search the tree when the tag is the direct child of <manifest> tag int type; final int searchDepth = parser.getDepth() + 1; @@ -506,6 +509,8 @@ public class ApkLiteParseUtils { } else if (TAG_RECEIVER.equals(parser.getName())) { hasDeviceAdminReceiver |= isDeviceAdminReceiver( parser, hasBindDeviceAdminPermission); + } else if (TAG_SDK_LIBRARY.equals(parser.getName())) { + isSdkLibrary = true; } } } else if (TAG_OVERLAY.equals(parser.getName())) { @@ -598,7 +603,7 @@ public class ApkLiteParseUtils { overlayIsStatic, overlayPriority, requiredSystemPropertyName, requiredSystemPropertyValue, minSdkVersion, targetSdkVersion, rollbackDataPolicy, requiredSplitTypes.first, requiredSplitTypes.second, - hasDeviceAdminReceiver)); + hasDeviceAdminReceiver, isSdkLibrary)); } private static boolean isDeviceAdminReceiver( diff --git a/core/java/android/content/pm/parsing/PackageLite.java b/core/java/android/content/pm/parsing/PackageLite.java index 5f5e81253b31..e2789c93516f 100644 --- a/core/java/android/content/pm/parsing/PackageLite.java +++ b/core/java/android/content/pm/parsing/PackageLite.java @@ -105,6 +105,10 @@ public class PackageLite { * or locally compiled variants. */ private final boolean mUseEmbeddedDex; + /** + * Indicates if this package is a sdk. + */ + private final boolean mIsSdkLibrary; public PackageLite(String path, String baseApkPath, ApkLite baseApk, String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames, @@ -131,6 +135,7 @@ public class PackageLite { mRequiredSplitTypes = requiredSplitTypes; mSplitRequired = (baseApk.isSplitRequired() || hasAnyRequiredSplitTypes()); mProfileableByShell = baseApk.isProfileableByShell(); + mIsSdkLibrary = baseApk.isIsSdkLibrary(); mSplitNames = splitNames; mSplitTypes = splitTypes; mIsFeatureSplits = isFeatureSplits; @@ -401,11 +406,20 @@ public class PackageLite { return mUseEmbeddedDex; } + /** + * Indicates if this package is a sdk. + */ + @DataClass.Generated.Member + public boolean isIsSdkLibrary() { + return mIsSdkLibrary; + } + @DataClass.Generated( - time = 1628562559343L, + time = 1643132127068L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java", - inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mTargetSdk\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)") + inputSignatures = + "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mTargetSdk\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\nprivate final boolean mIsSdkLibrary\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)") @Deprecated private void __metadata() {} diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index d9734b493471..5981d279227d 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -781,10 +781,11 @@ public final class StreamConfigurationMap { * <li>The fpsMin and fpsMax will be a multiple 30fps.</li> * <li>The fpsMin will be no less than 30fps, the fpsMax will be no less than 120fps.</li> * <li>At least one range will be a fixed FPS range where fpsMin == fpsMax.</li> - * <li>For each fixed FPS range, there will be one corresponding variable FPS range [30, - * fps_max]. These kinds of FPS ranges are suitable for preview-only use cases where the - * application doesn't want the camera device always produce higher frame rate than the display - * refresh rate.</li> + * <li>For each fixed FPS range, there will be one corresponding variable FPS range + * [30, fps_max] or [60, fps_max]. These kinds of FPS ranges are suitable for preview-only + * use cases where the application doesn't want the camera device always produce higher frame + * rate than the display refresh rate. Both 30fps and 60fps preview rate will not be + * supported for the same recording rate.</li> * </p> * * @return an array of supported high speed video recording FPS ranges The upper bound of diff --git a/core/java/android/inputmethodservice/ImsConfigurationTracker.java b/core/java/android/inputmethodservice/ImsConfigurationTracker.java index 3c788884371b..30ef0a2a6f7f 100644 --- a/core/java/android/inputmethodservice/ImsConfigurationTracker.java +++ b/core/java/android/inputmethodservice/ImsConfigurationTracker.java @@ -63,8 +63,9 @@ public final class ImsConfigurationTracker { */ @MainThread public void onBindInput(@Nullable Resources resources) { - Preconditions.checkState(mInitialized, - "onBindInput can be called only after onInitialize()."); + if (!mInitialized) { + return; + } if (mLastKnownConfig == null && resources != null) { mLastKnownConfig = new Configuration(resources.getConfiguration()); } diff --git a/core/java/android/inputmethodservice/navigationbar/ButtonDispatcher.java b/core/java/android/inputmethodservice/navigationbar/ButtonDispatcher.java index 3f26fa461097..6b2db7d01a54 100644 --- a/core/java/android/inputmethodservice/navigationbar/ButtonDispatcher.java +++ b/core/java/android/inputmethodservice/navigationbar/ButtonDispatcher.java @@ -67,7 +67,7 @@ final class ButtonDispatcher { } }; - public ButtonDispatcher(int id) { + ButtonDispatcher(int id) { mId = id; } @@ -125,8 +125,8 @@ final class ButtonDispatcher { public void setImageDrawable(KeyButtonDrawable drawable) { mImageDrawable = drawable; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { if (mViews.get(i) instanceof ButtonInterface) { ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable); } @@ -143,8 +143,8 @@ final class ButtonDispatcher { } mVisibility = visibility; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setVisibility(mVisibility); } } @@ -188,8 +188,8 @@ final class ButtonDispatcher { int nextAlpha = (int) (alpha * 255); if (prevAlpha != nextAlpha) { mAlpha = nextAlpha / 255f; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setAlpha(mAlpha); } } @@ -198,8 +198,8 @@ final class ButtonDispatcher { public void setDarkIntensity(float darkIntensity) { mDarkIntensity = darkIntensity; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { if (mViews.get(i) instanceof ButtonInterface) { ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity); } @@ -208,8 +208,8 @@ final class ButtonDispatcher { public void setDelayTouchFeedback(boolean delay) { mDelayTouchFeedback = delay; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { if (mViews.get(i) instanceof ButtonInterface) { ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay); } @@ -218,55 +218,55 @@ final class ButtonDispatcher { public void setOnClickListener(View.OnClickListener clickListener) { mClickListener = clickListener; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setOnClickListener(mClickListener); } } public void setOnTouchListener(View.OnTouchListener touchListener) { mTouchListener = touchListener; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setOnTouchListener(mTouchListener); } } public void setLongClickable(boolean isLongClickable) { mLongClickable = isLongClickable; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setLongClickable(mLongClickable); } } public void setOnLongClickListener(View.OnLongClickListener longClickListener) { mLongClickListener = longClickListener; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setOnLongClickListener(mLongClickListener); } } public void setOnHoverListener(View.OnHoverListener hoverListener) { mOnHoverListener = hoverListener; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setOnHoverListener(mOnHoverListener); } } public void setAccessibilityDelegate(AccessibilityDelegate delegate) { mAccessibilityDelegate = delegate; - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { mViews.get(i).setAccessibilityDelegate(delegate); } } public void setTranslation(int x, int y, int z) { - final int N = mViews.size(); - for (int i = 0; i < N; i++) { + final int numViews = mViews.size(); + for (int i = 0; i < numViews; i++) { final View view = mViews.get(i); view.setTranslationX(x); view.setTranslationY(y); diff --git a/core/java/android/inputmethodservice/navigationbar/DeadZone.java b/core/java/android/inputmethodservice/navigationbar/DeadZone.java index 4adc84bf0b6f..4cfd8139d912 100644 --- a/core/java/android/inputmethodservice/navigationbar/DeadZone.java +++ b/core/java/android/inputmethodservice/navigationbar/DeadZone.java @@ -82,7 +82,7 @@ final class DeadZone { } }; - public DeadZone(NavigationBarView view) { + DeadZone(NavigationBarView view) { mNavigationBarView = view; onConfigurationChanged(Surface.ROTATION_0); } @@ -92,13 +92,15 @@ final class DeadZone { } private float getSize(long now) { - if (mSizeMax == 0) + if (mSizeMax == 0) { return 0; + } long dt = (now - mLastPokeTime); - if (dt > mHold + mDecay) + if (dt > mHold + mDecay) { return mSizeMin; - if (dt < mHold) + } else if (dt < mHold) { return mSizeMax; + } return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay); } @@ -177,8 +179,9 @@ final class DeadZone { private void poke(MotionEvent event) { mLastPokeTime = event.getEventTime(); - if (DEBUG) + if (DEBUG) { Log.v(TAG, "poked! size=" + getSize(mLastPokeTime)); + } if (mShouldFlash) mNavigationBarView.postInvalidate(); } diff --git a/core/java/android/inputmethodservice/navigationbar/KeyButtonDrawable.java b/core/java/android/inputmethodservice/navigationbar/KeyButtonDrawable.java index 25a443de916b..45c8a186117d 100644 --- a/core/java/android/inputmethodservice/navigationbar/KeyButtonDrawable.java +++ b/core/java/android/inputmethodservice/navigationbar/KeyButtonDrawable.java @@ -54,30 +54,30 @@ import android.view.View; final class KeyButtonDrawable extends Drawable { public static final FloatProperty<KeyButtonDrawable> KEY_DRAWABLE_ROTATE = - new FloatProperty<KeyButtonDrawable>("KeyButtonRotation") { - @Override - public void setValue(KeyButtonDrawable drawable, float degree) { - drawable.setRotation(degree); - } + new FloatProperty<KeyButtonDrawable>("KeyButtonRotation") { + @Override + public void setValue(KeyButtonDrawable drawable, float degree) { + drawable.setRotation(degree); + } - @Override - public Float get(KeyButtonDrawable drawable) { - return drawable.getRotation(); - } - }; + @Override + public Float get(KeyButtonDrawable drawable) { + return drawable.getRotation(); + } + }; public static final FloatProperty<KeyButtonDrawable> KEY_DRAWABLE_TRANSLATE_Y = - new FloatProperty<KeyButtonDrawable>("KeyButtonTranslateY") { - @Override - public void setValue(KeyButtonDrawable drawable, float y) { - drawable.setTranslationY(y); - } + new FloatProperty<KeyButtonDrawable>("KeyButtonTranslateY") { + @Override + public void setValue(KeyButtonDrawable drawable, float y) { + drawable.setTranslationY(y); + } - @Override - public Float get(KeyButtonDrawable drawable) { - return drawable.getTranslationY(); - } - }; + @Override + public Float get(KeyButtonDrawable drawable) { + return drawable.getTranslationY(); + } + }; private final Paint mIconPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private final Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); @@ -100,7 +100,7 @@ final class KeyButtonDrawable extends Drawable { } }; - public KeyButtonDrawable(Drawable d, @ColorInt int lightColor, @ColorInt int darkColor, + KeyButtonDrawable(Drawable d, @ColorInt int lightColor, @ColorInt int darkColor, boolean horizontalFlip, Color ovalBackgroundColor) { this(d, new ShadowDrawableState(lightColor, darkColor, d instanceof AnimatedVectorDrawable, horizontalFlip, ovalBackgroundColor)); @@ -433,8 +433,8 @@ final class KeyButtonDrawable extends Drawable { final boolean mSupportsAnimation; final Color mOvalBackgroundColor; - public ShadowDrawableState(@ColorInt int lightColor, @ColorInt int darkColor, - boolean animated, boolean horizontalFlip, Color ovalBackgroundColor) { + ShadowDrawableState(@ColorInt int lightColor, @ColorInt int darkColor, boolean animated, + boolean horizontalFlip, Color ovalBackgroundColor) { mLightColor = lightColor; mDarkColor = darkColor; mSupportsAnimation = animated; diff --git a/core/java/android/inputmethodservice/navigationbar/KeyButtonRipple.java b/core/java/android/inputmethodservice/navigationbar/KeyButtonRipple.java index 38a63b661ac0..cf77c8989858 100644 --- a/core/java/android/inputmethodservice/navigationbar/KeyButtonRipple.java +++ b/core/java/android/inputmethodservice/navigationbar/KeyButtonRipple.java @@ -90,7 +90,7 @@ final class KeyButtonRipple extends Drawable { private Type mType = Type.ROUNDED_RECT; - public KeyButtonRipple(Context ctx, View targetView, @DimenRes int maxWidthResource) { + KeyButtonRipple(Context ctx, View targetView, @DimenRes int maxWidthResource) { mMaxWidthResource = maxWidthResource; mMaxWidth = ctx.getResources().getDimensionPixelSize(maxWidthResource); mTargetView = targetView; @@ -126,7 +126,7 @@ final class KeyButtonRipple extends Drawable { private void drawSoftware(Canvas canvas) { if (mGlowAlpha > 0f) { final Paint p = getRipplePaint(); - p.setAlpha((int)(mGlowAlpha * 255f)); + p.setAlpha((int) (mGlowAlpha * 255f)); final float w = getBounds().width(); final float h = getBounds().height(); @@ -412,7 +412,7 @@ final class KeyButtonRipple extends Drawable { mDrawingHardwareGlow = true; setExtendStart(CanvasProperty.createFloat(getExtendSize() / 2)); final RenderNodeAnimator startAnim = new RenderNodeAnimator(getExtendStart(), - getExtendSize()/2 - GLOW_MAX_SCALE_FACTOR * getRippleSize()/2); + getExtendSize() / 2 - GLOW_MAX_SCALE_FACTOR * getRippleSize() / 2); startAnim.setDuration(ANIMATION_DURATION_SCALE); startAnim.setInterpolator(mInterpolator); startAnim.addListener(mAnimatorListener); @@ -420,7 +420,7 @@ final class KeyButtonRipple extends Drawable { setExtendEnd(CanvasProperty.createFloat(getExtendSize() / 2)); final RenderNodeAnimator endAnim = new RenderNodeAnimator(getExtendEnd(), - getExtendSize()/2 + GLOW_MAX_SCALE_FACTOR * getRippleSize()/2); + getExtendSize() / 2 + GLOW_MAX_SCALE_FACTOR * getRippleSize() / 2); endAnim.setDuration(ANIMATION_DURATION_SCALE); endAnim.setInterpolator(mInterpolator); endAnim.addListener(mAnimatorListener); @@ -430,13 +430,13 @@ final class KeyButtonRipple extends Drawable { if (isHorizontal()) { mTopProp = CanvasProperty.createFloat(0f); mBottomProp = CanvasProperty.createFloat(getBounds().height()); - mRxProp = CanvasProperty.createFloat(getBounds().height()/2); - mRyProp = CanvasProperty.createFloat(getBounds().height()/2); + mRxProp = CanvasProperty.createFloat(getBounds().height() / 2); + mRyProp = CanvasProperty.createFloat(getBounds().height() / 2); } else { mLeftProp = CanvasProperty.createFloat(0f); mRightProp = CanvasProperty.createFloat(getBounds().width()); - mRxProp = CanvasProperty.createFloat(getBounds().width()/2); - mRyProp = CanvasProperty.createFloat(getBounds().width()/2); + mRxProp = CanvasProperty.createFloat(getBounds().width() / 2); + mRyProp = CanvasProperty.createFloat(getBounds().width() / 2); } mGlowScale = GLOW_MAX_SCALE_FACTOR; diff --git a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java index 74d30f8f8806..cfdb6caab9d3 100644 --- a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java +++ b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java @@ -200,8 +200,8 @@ public class KeyButtonView extends ImageView implements ButtonInterface { postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout()); break; case MotionEvent.ACTION_MOVE: - x = (int)ev.getRawX(); - y = (int)ev.getRawY(); + x = (int) ev.getRawX(); + y = (int) ev.getRawY(); float slop = getQuickStepTouchSlopPx(getContext()); if (Math.abs(x - mTouchDownX) > slop || Math.abs(y - mTouchDownY) > slop) { @@ -272,12 +272,13 @@ public class KeyButtonView extends ImageView implements ButtonInterface { : KeyButtonRipple.Type.ROUNDED_RECT); } + @Override public void playSoundEffect(int soundConstant) { if (!mPlaySounds) return; mAudioManager.playSoundEffect(soundConstant); } - public void sendEvent(int action, int flags) { + private void sendEvent(int action, int flags) { sendEvent(action, flags, SystemClock.uptimeMillis()); } @@ -309,8 +310,8 @@ public class KeyButtonView extends ImageView implements ButtonInterface { switch (action) { case KeyEvent.ACTION_DOWN: handled = ims.onKeyDown(ev.getKeyCode(), ev); - mTracking = handled && ev.getRepeatCount() == 0 && - (ev.getFlags() & KeyEvent.FLAG_START_TRACKING) != 0; + mTracking = handled && ev.getRepeatCount() == 0 + && (ev.getFlags() & KeyEvent.FLAG_START_TRACKING) != 0; break; case KeyEvent.ACTION_UP: handled = ims.onKeyUp(ev.getKeyCode(), ev); diff --git a/core/java/android/inputmethodservice/navigationbar/NavigationBarFrame.java b/core/java/android/inputmethodservice/navigationbar/NavigationBarFrame.java index f01173e0fdae..a270675239ee 100644 --- a/core/java/android/inputmethodservice/navigationbar/NavigationBarFrame.java +++ b/core/java/android/inputmethodservice/navigationbar/NavigationBarFrame.java @@ -59,4 +59,4 @@ public final class NavigationBarFrame extends FrameLayout { } return super.dispatchTouchEvent(event); } -}
\ No newline at end of file +} diff --git a/core/java/android/inputmethodservice/navigationbar/NavigationBarInflaterView.java b/core/java/android/inputmethodservice/navigationbar/NavigationBarInflaterView.java index d488890b27d4..e93bda2fa939 100644 --- a/core/java/android/inputmethodservice/navigationbar/NavigationBarInflaterView.java +++ b/core/java/android/inputmethodservice/navigationbar/NavigationBarInflaterView.java @@ -121,7 +121,7 @@ public final class NavigationBarInflaterView extends FrameLayout { return CONFIG_NAV_BAR_LAYOUT_HANDLE; } - public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) { + void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) { mButtonDispatchers = buttonDispatchers; for (int i = 0; i < buttonDispatchers.size(); i++) { initiallyFill(buttonDispatchers.valueAt(i)); @@ -376,7 +376,7 @@ public final class NavigationBarInflaterView extends FrameLayout { } */ - public static String extractSize(String buttonSpec) { + private static String extractSize(String buttonSpec) { if (!buttonSpec.contains(SIZE_MOD_START)) { return null; } @@ -384,7 +384,7 @@ public final class NavigationBarInflaterView extends FrameLayout { return buttonSpec.substring(sizeStart + 1, buttonSpec.indexOf(SIZE_MOD_END)); } - public static String extractButton(String buttonSpec) { + private static String extractButton(String buttonSpec) { if (!buttonSpec.contains(SIZE_MOD_START)) { return buttonSpec; } @@ -398,9 +398,9 @@ public final class NavigationBarInflaterView extends FrameLayout { mButtonDispatchers.valueAt(indexOfKey).addView(v); } if (v instanceof ViewGroup) { - final ViewGroup viewGroup = (ViewGroup)v; - final int N = viewGroup.getChildCount(); - for (int i = 0; i < N; i++) { + final ViewGroup viewGroup = (ViewGroup) v; + final int numChildViews = viewGroup.getChildCount(); + for (int i = 0; i < numChildViews; i++) { addToDispatchers(viewGroup.getChildAt(i)); } } diff --git a/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java b/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java index a2d71054c65d..510b14e7acd4 100644 --- a/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java +++ b/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java @@ -48,8 +48,8 @@ import java.util.function.Consumer; * @hide */ public final class NavigationBarView extends FrameLayout { - final static boolean DEBUG = false; - final static String TAG = "NavBarView"; + private static final boolean DEBUG = false; + private static final String TAG = "NavBarView"; // Copied from com.android.systemui.animation.Interpolators#FAST_OUT_SLOW_IN private static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -139,7 +139,7 @@ public final class NavigationBarView extends FrameLayout { } /** - * Applies {@param consumer} to each of the nav bar views. + * Applies {@code consumer} to each of the nav bar views. */ public void forEachView(Consumer<View> consumer) { if (mHorizontal != null) { @@ -181,7 +181,7 @@ public final class NavigationBarView extends FrameLayout { } } - public KeyButtonDrawable getBackDrawable() { + private KeyButtonDrawable getBackDrawable() { KeyButtonDrawable drawable = getDrawable(com.android.internal.R.drawable.ic_ime_nav_back); orientBackButton(drawable); return drawable; @@ -211,7 +211,7 @@ public final class NavigationBarView extends FrameLayout { // Animate the back button's rotation to the new degrees and only in portrait move up the // back button to line up with the other buttons float targetY = useAltBack - ? - dpToPx(NAVBAR_BACK_BUTTON_IME_OFFSET, getResources()) + ? -dpToPx(NAVBAR_BACK_BUTTON_IME_OFFSET, getResources()) : 0; ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable, PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_ROTATE, degrees), @@ -233,6 +233,11 @@ public final class NavigationBarView extends FrameLayout { super.setLayoutDirection(layoutDirection); } + /** + * Updates the navigation icons based on {@code hints}. + * + * @param hints bit flags defined in {@link StatusBarManager}. + */ public void setNavigationIconHints(int hints) { if (hints == mNavigationIconHints) return; final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0; @@ -250,15 +255,7 @@ public final class NavigationBarView extends FrameLayout { updateNavButtonIcons(); } - public void setDisabledFlags(int disabledFlags) { - if (mDisabledFlags == disabledFlags) return; - - mDisabledFlags = disabledFlags; - - updateNavButtonIcons(); - } - - public void updateNavButtonIcons() { + private void updateNavButtonIcons() { // We have to replace or restore the back and home button icons when exiting or entering // carmode, respectively. Recents are not available in CarMode in nav bar so change // to recent icon is not required. @@ -319,7 +316,7 @@ public final class NavigationBarView extends FrameLayout { mHorizontal.setVisibility(View.GONE); } - public void reorient() { + private void reorient() { updateCurrentView(); final android.inputmethodservice.navigationbar.NavigationBarFrame frame = @@ -372,6 +369,11 @@ public final class NavigationBarView extends FrameLayout { } } + /** + * Updates the dark intensity. + * + * @param intensity The intensity of darkness from {@code 0.0f} to {@code 1.0f}. + */ public void setDarkIntensity(@FloatRange(from = 0.0f, to = 1.0f) float intensity) { for (int i = 0; i < mButtonDispatchers.size(); ++i) { mButtonDispatchers.valueAt(i).setDarkIntensity(intensity); diff --git a/core/java/android/inputmethodservice/navigationbar/ReverseLinearLayout.java b/core/java/android/inputmethodservice/navigationbar/ReverseLinearLayout.java index 68163c35f784..9b36cc54b657 100644 --- a/core/java/android/inputmethodservice/navigationbar/ReverseLinearLayout.java +++ b/core/java/android/inputmethodservice/navigationbar/ReverseLinearLayout.java @@ -30,9 +30,8 @@ import java.util.ArrayList; /** * Automatically reverses the order of children as they are added. * Also reverse the width and height values of layout params - * @hide */ -public class ReverseLinearLayout extends LinearLayout { +class ReverseLinearLayout extends LinearLayout { /** If true, the layout is reversed vs. a regular linear layout */ private boolean mIsLayoutReverse; @@ -40,7 +39,7 @@ public class ReverseLinearLayout extends LinearLayout { /** If true, the layout is opposite to it's natural reversity from the layout direction */ private boolean mIsAlternativeOrder; - public ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) { + ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @@ -129,7 +128,7 @@ public class ReverseLinearLayout extends LinearLayout { public static class ReverseRelativeLayout extends RelativeLayout implements Reversible { - public ReverseRelativeLayout(Context context) { + ReverseRelativeLayout(Context context) { super(context); } diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index 010459d06e8d..9e47a708162d 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -293,7 +293,10 @@ public interface IBinder { * * @return Returns the result from {@link Binder#onTransact}. A successful call * generally returns true; false generally means the transaction code was not - * understood. + * understood. For a oneway call to a different process false should never be + * returned. If a oneway call is made to code in the same process (usually to + * a C++ or Rust implementation), then there are no oneway semantics, and + * false can still be returned. */ public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException; diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 39ca596f9181..3cde0319efd3 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -109,7 +109,7 @@ interface IUserManager { boolean someUserHasAccount(in String accountName, in String accountType); String getProfileType(int userId); boolean isMediaSharedWithParent(int userId); - boolean isCredentialSharedWithParent(int userId); + boolean isCredentialSharableWithParent(int userId); boolean isDemoUser(int userId); boolean isPreCreated(int userId); UserInfo createProfileForUserEvenWhenDisallowedWithThrow(in String name, in String userType, int flags, diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a715c6961359..276578ea3c1f 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -4763,7 +4763,7 @@ public class UserManager { } /** - * Returns {@code true} if the user shares lock settings credential with its parent user + * Returns whether the user can have shared lockscreen credential with its parent user. * * This API only works for {@link UserManager#isProfile() profiles} * and will always return false for any other user type. @@ -4776,9 +4776,9 @@ public class UserManager { Manifest.permission.MANAGE_USERS, Manifest.permission.INTERACT_ACROSS_USERS}) @SuppressAutoDoc - public boolean isCredentialSharedWithParent() { + public boolean isCredentialSharableWithParent() { try { - return mService.isCredentialSharedWithParent(mUserId); + return mService.isCredentialSharableWithParent(mUserId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index cfef7adb240f..a6ad5e5863df 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10729,14 +10729,6 @@ public final class Settings { "communal_mode_trusted_networks"; /** - * Setting to allow Fast Pair scans to be enabled. - * @hide - */ - @SystemApi - @Readable - public static final String FAST_PAIR_SCAN_ENABLED = "fast_pair_scan_enabled"; - - /** * Setting to store denylisted system languages by the CEC {@code <Set Menu Language>} * confirmation dialog. * diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 1fd75e610097..001707d228b6 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -231,7 +231,7 @@ public class DreamService extends Service implements Window.Callback { * The default value for whether to show complications on the overlay. * @hide */ - public static final boolean DEFAULT_SHOW_COMPLICATIONS = true; + public static final boolean DEFAULT_SHOW_COMPLICATIONS = false; private final IDreamManager mDreamManager; private final Handler mHandler = new Handler(Looper.getMainLooper()); diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index fe6ae78ccf2d..34e7ea74a2db 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -96,7 +96,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true"); DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true"); DEFAULT_FLAGS.put("settings_search_always_expand", "true"); - DEFAULT_FLAGS.put(SETTINGS_APP_LANGUAGE_SELECTION, "true"); + DEFAULT_FLAGS.put(SETTINGS_APP_LANGUAGE_SELECTION, "false"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true"); DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "false"); DEFAULT_FLAGS.put(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE, "true"); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 71c1b7c47a9f..a4841f6f0d95 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -23,6 +23,7 @@ import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.toInternalType; import static android.view.InsetsState.toPublicType; +import static android.view.ViewRootImpl.CAPTION_ON_SHELL; import static android.view.WindowInsets.Type.all; import static android.view.WindowInsets.Type.ime; @@ -682,9 +683,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public boolean onStateChanged(InsetsState state) { - boolean stateChanged = !mState.equals(state, true /* excludingCaptionInsets */, - false /* excludeInvisibleIme */) - || !captionInsetsUnchanged(); + boolean stateChanged = false; + if (!CAPTION_ON_SHELL) { + stateChanged = !mState.equals(state, true /* excludingCaptionInsets */, + false /* excludeInvisibleIme */) + || captionInsetsUnchanged(); + } else { + stateChanged = !mState.equals(state, false /* excludingCaptionInsets */, + false /* excludeInvisibleIme */); + } if (!stateChanged && mLastDispatchedState.equals(state)) { return false; } @@ -758,16 +765,20 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } private boolean captionInsetsUnchanged() { + if (CAPTION_ON_SHELL) { + return false; + } if (mState.peekSource(ITYPE_CAPTION_BAR) == null && mCaptionInsetsHeight == 0) { - return true; + return false; } if (mState.peekSource(ITYPE_CAPTION_BAR) != null && mCaptionInsetsHeight == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) { - return true; + return false; } - return false; + + return true; } private void startResizingAnimationIfNeeded(InsetsState fromState) { @@ -1582,11 +1593,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void setCaptionInsetsHeight(int height) { + // This method is to be removed once the caption is moved to the shell. + if (CAPTION_ON_SHELL) { + return; + } if (mCaptionInsetsHeight != height) { mCaptionInsetsHeight = height; if (mCaptionInsetsHeight != 0) { - mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top, - mFrame.right, mFrame.top + mCaptionInsetsHeight)); + mState.getSource(ITYPE_CAPTION_BAR).setFrame(mFrame.left, mFrame.top, + mFrame.right, mFrame.top + mCaptionInsetsHeight); } else { mState.removeSource(ITYPE_CAPTION_BAR); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index bde761e59620..18e65c9f3a37 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -277,6 +277,12 @@ public final class ViewRootImpl implements ViewParent, private static final boolean ENABLE_INPUT_LATENCY_TRACKING = true; /** + * Whether the caption is drawn by the shell. + * @hide + */ + public static final boolean CAPTION_ON_SHELL = false; + + /** * Set this system property to true to force the view hierarchy to render * at 60 Hz. This can be used to measure the potential framerate. */ @@ -2561,6 +2567,9 @@ public final class ViewRootImpl implements ViewParent, } private boolean updateCaptionInsets() { + if (CAPTION_ON_SHELL) { + return false; + } if (!(mView instanceof DecorView)) return false; final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight(); final Rect captionFrame = new Rect(); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 3a7a544a334b..7f8a68dbd0ea 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -4595,7 +4595,7 @@ public class Editor { if (includeEditorBounds) { final RectF bounds = new RectF(); - mTextView.getBoundsOnScreen(bounds, false /* clipToParent */); + bounds.set(0 /* left */, 0 /* top */, mTextView.getWidth(), mTextView.getHeight()); EditorBoundsInfo.Builder boundsBuilder = new EditorBoundsInfo.Builder(); //TODO(b/210039666): add Handwriting bounds once they're available. builder.setEditorBoundsInfo( diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 40e40856b000..89ac72255306 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -30,6 +30,7 @@ import static android.view.View.MeasureSpec.EXACTLY; import static android.view.View.MeasureSpec.getMode; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static android.view.ViewRootImpl.CAPTION_ON_SHELL; import static android.view.Window.DECOR_CAPTION_SHADE_DARK; import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; @@ -2120,7 +2121,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind * corresponding insets change to the InsetsController. */ public void notifyCaptionHeightChanged() { - getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight()); + if (!CAPTION_ON_SHELL) { + getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight()); + } } void setWindow(PhoneWindow phoneWindow) { diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 82ae42441032..f83579207e31 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -808,7 +808,7 @@ public class LockPatternUtils { */ public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, LockscreenCredential profilePassword) { - if (!isCredentialSharedWithParent(userHandle)) { + if (!isCredentialSharableWithParent(userHandle)) { return; } try { @@ -824,7 +824,7 @@ public class LockPatternUtils { * Returns true if {@code userHandle} is a managed profile with separate challenge. */ public boolean isSeparateProfileChallengeEnabled(int userHandle) { - return isCredentialSharedWithParent(userHandle) && hasSeparateChallenge(userHandle); + return isCredentialSharableWithParent(userHandle) && hasSeparateChallenge(userHandle); } /** @@ -849,8 +849,8 @@ public class LockPatternUtils { return info != null && info.isManagedProfile(); } - private boolean isCredentialSharedWithParent(int userHandle) { - return getUserManager(userHandle).isCredentialSharedWithParent(); + private boolean isCredentialSharableWithParent(int userHandle) { + return getUserManager(userHandle).isCredentialSharableWithParent(); } /** diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index 2b6b933c6886..01cec7727c4e 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -45,6 +45,7 @@ import android.util.AttributeSet; import android.util.IntArray; import android.util.Log; import android.util.SparseArray; +import android.util.TypedValue; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.RenderNodeAnimator; @@ -82,10 +83,12 @@ public class LockPatternView extends View { private static final int DOT_ACTIVATION_DURATION_MILLIS = 50; private static final int DOT_RADIUS_INCREASE_DURATION_MILLIS = 96; private static final int DOT_RADIUS_DECREASE_DURATION_MILLIS = 192; + private static final float MIN_DOT_HIT_FACTOR = 0.2f; private final CellState[][] mCellStates; private final int mDotSize; private final int mDotSizeActivated; + private final float mDotHitFactor; private final int mPathWidth; private boolean mDrawingProfilingStarted = false; @@ -143,12 +146,11 @@ public class LockPatternView extends View { private boolean mPatternInProgress = false; private boolean mFadePattern = true; - private float mHitFactor = 0.6f; - @UnsupportedAppUsage private float mSquareWidth; @UnsupportedAppUsage private float mSquareHeight; + private float mDotHitRadius; private final LinearGradient mFadeOutGradientShader; private final Path mCurrentPath = new Path(); @@ -164,8 +166,7 @@ public class LockPatternView extends View { private final Interpolator mFastOutSlowInInterpolator; private final Interpolator mLinearOutSlowInInterpolator; - private PatternExploreByTouchHelper mExploreByTouchHelper; - private AudioManager mAudioManager; + private final PatternExploreByTouchHelper mExploreByTouchHelper; private Drawable mSelectedDrawable; private Drawable mNotSelectedDrawable; @@ -349,6 +350,9 @@ public class LockPatternView extends View { mDotSize = getResources().getDimensionPixelSize(R.dimen.lock_pattern_dot_size); mDotSizeActivated = getResources().getDimensionPixelSize( R.dimen.lock_pattern_dot_size_activated); + TypedValue outValue = new TypedValue(); + getResources().getValue(R.dimen.lock_pattern_dot_hit_factor, outValue, true); + mDotHitFactor = Math.max(Math.min(outValue.getFloat(), 1f), MIN_DOT_HIT_FACTOR); mUseLockPatternDrawable = getResources().getBoolean(R.bool.use_lock_pattern_drawable); if (mUseLockPatternDrawable) { @@ -375,7 +379,6 @@ public class LockPatternView extends View { AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); mExploreByTouchHelper = new PatternExploreByTouchHelper(this); setAccessibilityDelegate(mExploreByTouchHelper); - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); int fadeAwayGradientWidth = getResources().getDimensionPixelSize( R.dimen.lock_pattern_fade_away_gradient_width); @@ -679,6 +682,7 @@ public class LockPatternView extends View { final int height = h - mPaddingTop - mPaddingBottom; mSquareHeight = height / 3.0f; mExploreByTouchHelper.invalidateRoot(); + mDotHitRadius = Math.min(mSquareHeight / 2, mSquareWidth / 2) * mDotHitFactor; if (mUseLockPatternDrawable) { mNotSelectedDrawable.setBounds(mPaddingLeft, mPaddingTop, width, height); @@ -890,63 +894,30 @@ public class LockPatternView extends View { return set; } - // helper method to find which cell a point maps to + @Nullable private Cell checkForNewHit(float x, float y) { - - final int rowHit = getRowHit(y); - if (rowHit < 0) { - return null; - } - final int columnHit = getColumnHit(x); - if (columnHit < 0) { - return null; - } - - if (mPatternDrawLookup[rowHit][columnHit]) { - return null; - } - return Cell.of(rowHit, columnHit); - } - - /** - * Helper method to find the row that y falls into. - * @param y The y coordinate - * @return The row that y falls in, or -1 if it falls in no row. - */ - private int getRowHit(float y) { - - final float squareHeight = mSquareHeight; - float hitSize = squareHeight * mHitFactor; - - float offset = mPaddingTop + (squareHeight - hitSize) / 2f; - for (int i = 0; i < 3; i++) { - - final float hitTop = offset + squareHeight * i; - if (y >= hitTop && y <= hitTop + hitSize) { - return i; - } + Cell cellHit = detectCellHit(x, y); + if (cellHit != null && !mPatternDrawLookup[cellHit.row][cellHit.column]) { + return cellHit; } - return -1; + return null; } - /** - * Helper method to find the column x fallis into. - * @param x The x coordinate. - * @return The column that x falls in, or -1 if it falls in no column. - */ - private int getColumnHit(float x) { - final float squareWidth = mSquareWidth; - float hitSize = squareWidth * mHitFactor; - - float offset = mPaddingLeft + (squareWidth - hitSize) / 2f; - for (int i = 0; i < 3; i++) { - - final float hitLeft = offset + squareWidth * i; - if (x >= hitLeft && x <= hitLeft + hitSize) { - return i; + /** Helper method to find which cell a point maps to. */ + @Nullable + private Cell detectCellHit(float x, float y) { + final float hitRadiusSquared = mDotHitRadius * mDotHitRadius; + for (int row = 0; row < 3; row++) { + for (int column = 0; column < 3; column++) { + float centerY = getCenterYForRow(row); + float centerX = getCenterXForColumn(column); + if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) + < hitRadiusSquared) { + return Cell.of(row, column); + } } } - return -1; + return null; } @Override @@ -1553,8 +1524,7 @@ public class LockPatternView extends View { protected int getVirtualViewAt(float x, float y) { // This must use the same hit logic for the screen to ensure consistency whether // accessibility is on or off. - int id = getVirtualViewIdForHit(x, y); - return id; + return getVirtualViewIdForHit(x, y); } @Override @@ -1670,12 +1640,11 @@ public class LockPatternView extends View { final int col = ordinal % 3; float centerX = getCenterXForColumn(col); float centerY = getCenterYForRow(row); - float cellheight = mSquareHeight * mHitFactor * 0.5f; - float cellwidth = mSquareWidth * mHitFactor * 0.5f; - bounds.left = (int) (centerX - cellwidth); - bounds.right = (int) (centerX + cellwidth); - bounds.top = (int) (centerY - cellheight); - bounds.bottom = (int) (centerY + cellheight); + float cellHitRadius = mDotHitRadius; + bounds.left = (int) (centerX - cellHitRadius); + bounds.right = (int) (centerX + cellHitRadius); + bounds.top = (int) (centerY - cellHitRadius); + bounds.bottom = (int) (centerY + cellHitRadius); return bounds; } @@ -1694,16 +1663,12 @@ public class LockPatternView extends View { * @return VIRTUAL_BASE_VIEW_ID+id or 0 if no view was hit */ private int getVirtualViewIdForHit(float x, float y) { - final int rowHit = getRowHit(y); - if (rowHit < 0) { - return ExploreByTouchHelper.INVALID_ID; - } - final int columnHit = getColumnHit(x); - if (columnHit < 0) { + Cell cellHit = detectCellHit(x, y); + if (cellHit == null) { return ExploreByTouchHelper.INVALID_ID; } - boolean dotAvailable = mPatternDrawLookup[rowHit][columnHit]; - int dotId = (rowHit * 3 + columnHit) + VIRTUAL_BASE_VIEW_ID; + boolean dotAvailable = mPatternDrawLookup[cellHit.row][cellHit.column]; + int dotId = (cellHit.row * 3 + cellHit.column) + VIRTUAL_BASE_VIEW_ID; int view = dotAvailable ? dotId : ExploreByTouchHelper.INVALID_ID; if (DEBUG_A11Y) Log.v(TAG, "getVirtualViewIdForHit(" + x + "," + y + ") => " + view + "avail =" + dotAvailable); diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 5b7092cabfcb..7bc69055292d 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -895,7 +895,7 @@ void SetThreadName(const std::string& thread_name) { // pthread_setname_np fails rather than truncating long strings. char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded into bionic - strlcpy(buf, name_start_ptr, sizeof(buf) - 1); + strlcpy(buf, name_start_ptr, sizeof(buf)); errno = pthread_setname_np(pthread_self(), buf); if (errno != 0) { ALOGW("Unable to set the name of current thread to '%s': %s", buf, strerror(errno)); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 21baa0bcea97..becac7f96428 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1901,11 +1901,21 @@ <!-- Allows applications to enable/disable wifi auto join. This permission is used to let OEMs grant their trusted app access to a subset of privileged wifi APIs to improve wifi performance. - <p>Not for use by third-party applications. --> + <p>Not for use by third-party applications. + @deprecated will be replaced with MANAGE_WIFI_NETWORK_SELECTION --> <permission android:name="android.permission.MANAGE_WIFI_AUTO_JOIN" android:protectionLevel="signature|privileged|knownSigner" android:knownCerts="@array/wifi_known_signers" /> + <!-- This permission is used to let OEMs grant their trusted app access to a subset of + privileged wifi APIs to improve wifi performance. Allows applications to manage + Wi-Fi network selection related features such as enable or disable global auto-join, + modify connectivity scan intervals, and approve Wi-Fi Direct connections. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.MANAGE_WIFI_NETWORK_SELECTION" + android:protectionLevel="signature|privileged|knownSigner" + android:knownCerts="@array/wifi_known_signers" /> + <!-- Allows applications to get notified when a Wi-Fi interface request cannot be satisfied without tearing down one or more other interfaces, and provide a decision whether to approve the request or reject it. @@ -3089,7 +3099,7 @@ <p>Not for use by third-party applications. --> <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY" - android:protectionLevel="signature|recents|role"/> + android:protectionLevel="signature|recents|role|installer"/> <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} @hide @@ -6829,6 +6839,13 @@ </intent-filter> </receiver> + <receiver android:name="com.android.server.sdksandbox.SdkSandboxVerifierReceiver" + android:exported="false"> + <intent-filter> + <action android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION"/> + </intent-filter> + </receiver> + <service android:name="android.hardware.location.GeofenceHardwareService" android:permission="android.permission.LOCATION_HARDWARE" android:exported="false" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 0bdf71667783..0a572be35023 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2335,7 +2335,7 @@ <!-- Remote server that can provide NTP responses. --> <string translatable="false" name="config_ntpServer">time.android.com</string> <!-- Normal polling frequency in milliseconds --> - <integer name="config_ntpPollingInterval">86400000</integer> + <integer name="config_ntpPollingInterval">64800000</integer> <!-- Try-again polling interval in milliseconds, in case the network request failed --> <integer name="config_ntpPollingIntervalShorter">60000</integer> <!-- Number of times to try again with the shorter interval, before backing diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 1b9f7feec0ef..44c551259375 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -668,6 +668,9 @@ <dimen name="lock_pattern_dot_line_width">22dp</dimen> <dimen name="lock_pattern_dot_size">14dp</dimen> <dimen name="lock_pattern_dot_size_activated">30dp</dimen> + <!-- How much of the cell space is classified as hit areas [0..1] where 1 means that hit area is + a circle with diameter equals to cell minimum side min(width, height). --> + <item type="dimen" format="float" name="lock_pattern_dot_hit_factor">0.6</item> <!-- Width of a gradient applied to a lock pattern line while its disappearing animation. --> <dimen name="lock_pattern_fade_away_gradient_width">8dp</dimen> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 602e42d2dc28..5de8feca01dc 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1248,14 +1248,13 @@ Malicious apps may use this to erase or modify your call log.</string> <!-- Title of the body sensors permission, listed so the user can decide whether to allow the application to access body sensor data. [CHAR LIMIT=80] --> - <string name="permlab_bodySensors">access body sensors (like heart rate monitors) - </string> + <string name="permlab_bodySensors">Access body sensor data, like heart rate, while in use</string> <!-- Description of the body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors. [CHAR LIMIT=NONE] --> - <string name="permdesc_bodySensors" product="default">Access to data from body sensors such as heart rate, temperature, blood oxygen percentage, etc.</string> + <string name="permdesc_bodySensors" product="default">Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in use.</string> <!-- Title of the background body sensors permission, listed so the user can decide whether to allow the application to access body sensor data in the background. [CHAR LIMIT=80] --> - <string name="permlab_bodySensors_background">access body sensors (like heart rate monitors) while in the background</string> + <string name="permlab_bodySensors_background">Access body sensor data, like heart rate, while in the background</string> <!-- Description of the background body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors in the background. [CHAR LIMIT=NONE] --> - <string name="permdesc_bodySensors_background" product="default">Access to data from body sensors such as heart rate, temperature, blood oxygen percentage, etc. while in the background.</string> + <string name="permdesc_bodySensors_background" product="default">Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in the background.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_readCalendar">Read calendar events and details</string> @@ -2415,7 +2414,7 @@ <!-- On the unlock pattern screen, shown at the top of the unlock screen to tell the user what to do. Below this text is the place for theu ser to draw the pattern. --> <string name="lockscreen_pattern_instructions">Draw pattern to unlock</string> <!-- Button at the bottom of the unlock screen to make an emergency call or access other emergency assistance functions. --> - <string name="lockscreen_emergency_call">Emergency call</string> + <string name="lockscreen_emergency_call">Emergency</string> <!-- Button at the bottom of the unlock screen that lets the user return to a call --> <string name="lockscreen_return_to_call">Return to call</string> <!-- Shown to confirm that the user entered their lock pattern correctly. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 8f3abd60dd3c..6f34b3f899f1 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1325,6 +1325,7 @@ <java-symbol type="dimen" name="lock_pattern_dot_line_width" /> <java-symbol type="dimen" name="lock_pattern_dot_size" /> <java-symbol type="dimen" name="lock_pattern_dot_size_activated" /> + <java-symbol type="dimen" name="lock_pattern_dot_hit_factor" /> <java-symbol type="dimen" name="lock_pattern_fade_away_gradient_width" /> <java-symbol type="drawable" name="clock_dial" /> <java-symbol type="drawable" name="clock_hand_hour" /> diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 227a86576113..c504f0cf2d94 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -30,6 +30,7 @@ import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.LAST_TYPE; +import static android.view.ViewRootImpl.CAPTION_ON_SHELL; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; @@ -758,6 +759,11 @@ public class InsetsControllerTest { @Test public void testCaptionInsetsStateAssemble() { + if (CAPTION_ON_SHELL) { + // For this case, the test is covered by WindowContainerInsetsSourceProviderTest, This + // test can be removed after the caption is moved to shell completely. + return; + } InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { mController.onFrameChanged(new Rect(0, 0, 100, 300)); final InsetsState state = new InsetsState(mController.getState(), true); @@ -769,6 +775,7 @@ public class InsetsControllerTest { assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame()); assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/, true /* excludeInvisibleIme */)); + // Test update to remove the caption bar mController.setCaptionInsetsHeight(0); mController.onStateChanged(state); // The caption bar source should not be there at all, because we don't add empty @@ -779,6 +786,11 @@ public class InsetsControllerTest { @Test public void testNotifyCaptionInsetsOnlyChange() { + if (CAPTION_ON_SHELL) { + // For this case, the test is covered by WindowContainerInsetsSourceProviderTest, This + // test can be removed after the caption is moved to shell completely. + return; + } InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { final InsetsState state = new InsetsState(mController.getState(), true); reset(mTestHost); diff --git a/core/tests/coretests/src/com/android/internal/widget/LockPatternViewTest.java b/core/tests/coretests/src/com/android/internal/widget/LockPatternViewTest.java new file mode 100644 index 000000000000..8ba49663ad09 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/widget/LockPatternViewTest.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +import android.content.Context; + +import androidx.test.annotation.UiThreadTest; + +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toolbar; + + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.rule.UiThreadTestRule; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import com.android.internal.R; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +@RunWith(Parameterized.class) +@SmallTest +public class LockPatternViewTest { + + @Rule + public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); + + private final int mViewSize; + private final float mDefaultError; + private final float mDot1x; + private final float mDot1y; + private final float mDot2x; + private final float mDot2y; + private final float mDot3x; + private final float mDot3y; + private final float mDot5x; + private final float mDot5y; + private final float mDot7x; + private final float mDot7y; + private final float mDot9x; + private final float mDot9y; + + private Context mContext; + private LockPatternView mLockPatternView; + @Mock + private LockPatternView.OnPatternListener mPatternListener; + @Captor + private ArgumentCaptor<List<LockPatternView.Cell>> mCellsArgumentCaptor; + + public LockPatternViewTest(int viewSize) { + mViewSize = viewSize; + float cellSize = viewSize / 3f; + mDefaultError = cellSize * 0.2f; + mDot1x = cellSize / 2f; + mDot1y = cellSize / 2f; + mDot2x = cellSize + mDot1x; + mDot2y = mDot1y; + mDot3x = cellSize + mDot2x; + mDot3y = mDot1y; + // dot4 is skipped as redundant + mDot5x = cellSize + mDot1x; + mDot5y = cellSize + mDot1y; + // dot6 is skipped as redundant + mDot7x = mDot1x; + mDot7y = cellSize * 2 + mDot1y; + // dot8 is skipped as redundant + mDot9x = cellSize * 2 + mDot7x; + mDot9y = mDot7y; + } + + @Parameterized.Parameters + public static Collection primeNumbers() { + return Arrays.asList(192, 512, 768, 1024); + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mContext = InstrumentationRegistry.getContext(); + mLockPatternView = new LockPatternView(mContext, null); + int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(mViewSize, + View.MeasureSpec.EXACTLY); + int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(mViewSize, + View.MeasureSpec.EXACTLY); + mLockPatternView.measure(widthMeasureSpec, heightMeasureSpec); + mLockPatternView.layout(0, 0, mLockPatternView.getMeasuredWidth(), + mLockPatternView.getMeasuredHeight()); + } + + @UiThreadTest + @Test + public void downStartsPattern() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, mDot1x, mDot1y, 1)); + verify(mPatternListener).onPatternStart(); + } + + @UiThreadTest + @Test + public void up_completesPattern() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, mDot1x, mDot1y, 1)); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, mDot1x, mDot1y, 1)); + verify(mPatternListener).onPatternDetected(any()); + } + + @UiThreadTest + @Test + public void moveToDot_hitsDot() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1f, 1f, 1)); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, mDot1x, mDot1y, 1)); + verify(mPatternListener).onPatternStart(); + } + + @UiThreadTest + @Test + public void moveOutside_doesNotHitsDot() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1f, 1f, 1)); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 2f, 2f, 1)); + verify(mPatternListener, never()).onPatternStart(); + } + + @UiThreadTest + @Test + public void moveAlongTwoDots_hitsTwo() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1f, 1f, 1)); + makeMove(mDot1x, mDot1y, mDot2x, mDot2y, 6); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, mDot2x, mDot2y, 1)); + + verify(mPatternListener).onPatternDetected(mCellsArgumentCaptor.capture()); + List<LockPatternView.Cell> patternCells = mCellsArgumentCaptor.getValue(); + assertThat(patternCells, hasSize(2)); + assertThat(patternCells, + contains(LockPatternView.Cell.of(0, 0), LockPatternView.Cell.of(0, 1))); + } + + @UiThreadTest + @Test + public void moveAlongTwoDotsDiagonally_hitsTwo() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1f, 1f, 1)); + makeMove(mDot1x, mDot1y, mDot5x, mDot5y, 6); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, mDot5x, mDot5y, 1)); + + verify(mPatternListener).onPatternDetected(mCellsArgumentCaptor.capture()); + List<LockPatternView.Cell> patternCells = mCellsArgumentCaptor.getValue(); + assertThat(patternCells, hasSize(2)); + assertThat(patternCells, + contains(LockPatternView.Cell.of(0, 0), LockPatternView.Cell.of(1, 1))); + } + + @UiThreadTest + @Test + public void moveAlongZPattern_hitsDots() { + mLockPatternView.setOnPatternListener(mPatternListener); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1f, 1f, 1)); + makeMove(mDot1x, mDot1y, mDot3x + mDefaultError, mDot3y, 10); + makeMove(mDot3x - mDefaultError, mDot3y, mDot7x, mDot7y, 10); + makeMove(mDot7x, mDot7y - mDefaultError, mDot9x, mDot9y - mDefaultError, 10); + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, mViewSize - mDefaultError, + mViewSize - mDefaultError, 1)); + + verify(mPatternListener).onPatternDetected(mCellsArgumentCaptor.capture()); + List<LockPatternView.Cell> patternCells = mCellsArgumentCaptor.getValue(); + assertThat(patternCells, hasSize(7)); + assertThat(patternCells, + contains(LockPatternView.Cell.of(0, 0), + LockPatternView.Cell.of(0, 1), + LockPatternView.Cell.of(0, 2), + LockPatternView.Cell.of(1, 1), + LockPatternView.Cell.of(2, 0), + LockPatternView.Cell.of(2, 1), + LockPatternView.Cell.of(2, 2))); + } + + private void makeMove(float xFrom, float yFrom, float xTo, float yTo, int numberOfSteps) { + for (int i = 0; i < numberOfSteps; i++) { + float progress = i / (numberOfSteps - 1f); + float rest = 1f - progress; + mLockPatternView.onTouchEvent( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, + /* x= */ xFrom * rest + xTo * progress, + /* y= */ yFrom * rest + yTo * progress, + 1)); + } + } +} diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index 31dd10a8ed53..e7961c94928c 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -108,6 +108,16 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } } + /** + * XDH represents Curve 25519 providers. + */ + public static class XDH extends AndroidKeyStoreKeyPairGeneratorSpi { + // XDH is treated as EC. + public XDH() { + super(KeymasterDefs.KM_ALGORITHM_EC); + } + } + /* * These must be kept in sync with system/security/keystore/defaults.h */ @@ -242,6 +252,23 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } catch (NullPointerException | IllegalArgumentException e) { throw new InvalidAlgorithmParameterException(e); } + } else if (params instanceof NamedParameterSpec) { + NamedParameterSpec namedSpec = (NamedParameterSpec) params; + // Android Keystore cannot support initialization from a NamedParameterSpec + // because an alias for the key is needed (a KeyGenParameterSpec cannot be + // constructed). + if (namedSpec.getName().equalsIgnoreCase(NamedParameterSpec.X25519.getName()) + || namedSpec.getName().equalsIgnoreCase( + NamedParameterSpec.ED25519.getName())) { + throw new IllegalArgumentException( + "This KeyPairGenerator cannot be initialized using NamedParameterSpec." + + " use " + KeyGenParameterSpec.class.getName() + " or " + + KeyPairGeneratorSpec.class.getName()); + } else { + throw new InvalidAlgorithmParameterException( + "Unsupported algorithm specified via NamedParameterSpec: " + + namedSpec.getName()); + } } else { throw new InvalidAlgorithmParameterException( "Unsupported params class: " + params.getClass().getName() diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java index e5d127609b2e..d31499e8b36d 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java @@ -83,10 +83,12 @@ public class AndroidKeyStoreProvider extends Provider { // java.security.KeyPairGenerator put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC"); put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA"); + put("KeyPairGenerator.XDH", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$XDH"); // java.security.KeyFactory putKeyFactoryImpl("EC"); putKeyFactoryImpl("RSA"); + putKeyFactoryImpl("XDH"); // javax.crypto.KeyGenerator put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES"); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java index 89d7a407e459..b3becad3dc5a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java @@ -33,6 +33,12 @@ import androidx.annotation.NonNull; * The base adapter can be used for {@link RemoteAnimationTarget} that is simple open/close. */ class TaskFragmentAnimationAdapter { + + /** + * If {@link #mOverrideLayer} is set to this value, we don't want to override the surface layer. + */ + private static final int LAYER_NO_OVERRIDE = -1; + final Animation mAnimation; final RemoteAnimationTarget mTarget; final SurfaceControl mLeash; @@ -42,6 +48,7 @@ class TaskFragmentAnimationAdapter { final float[] mVecs = new float[4]; final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; + private int mOverrideLayer = LAYER_NO_OVERRIDE; TaskFragmentAnimationAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) { @@ -58,10 +65,21 @@ class TaskFragmentAnimationAdapter { mLeash = leash; } + /** + * Surface layer to be set at the first frame of the animation. We will not set the layer if it + * is set to {@link #LAYER_NO_OVERRIDE}. + */ + final void overrideLayer(int layer) { + mOverrideLayer = layer; + } + /** Called on frame update. */ final void onAnimationUpdate(@NonNull SurfaceControl.Transaction t, long currentPlayTime) { if (mIsFirstFrame) { t.show(mLeash); + if (mOverrideLayer != LAYER_NO_OVERRIDE) { + t.setLayer(mLeash, mOverrideLayer); + } mIsFirstFrame = false; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index 46bdf6d0e689..1ac33173668b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -25,6 +25,7 @@ import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN; import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; +import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; import android.animation.ValueAnimator; @@ -181,18 +182,22 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { private List<TaskFragmentAnimationAdapter> createOpenAnimationAdapters( @NonNull RemoteAnimationTarget[] targets) { - return createOpenCloseAnimationAdapters(targets, + return createOpenCloseAnimationAdapters(targets, true /* isOpening */, mAnimationSpec::loadOpenAnimation); } private List<TaskFragmentAnimationAdapter> createCloseAnimationAdapters( @NonNull RemoteAnimationTarget[] targets) { - return createOpenCloseAnimationAdapters(targets, + return createOpenCloseAnimationAdapters(targets, false /* isOpening */, mAnimationSpec::loadCloseAnimation); } + /** + * Creates {@link TaskFragmentAnimationAdapter} for OPEN and CLOSE types of transition. + * @param isOpening {@code true} for OPEN type, {@code false} for CLOSE type. + */ private List<TaskFragmentAnimationAdapter> createOpenCloseAnimationAdapters( - @NonNull RemoteAnimationTarget[] targets, + @NonNull RemoteAnimationTarget[] targets, boolean isOpening, @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider) { // We need to know if the target window is only a partial of the whole animation screen. // If so, we will need to adjust it to make the whole animation screen looks like one. @@ -210,14 +215,25 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { } } + // For OPEN transition, open windows should be above close windows. + // For CLOSE transition, open windows should be below close windows. + int offsetLayer = TYPE_LAYER_OFFSET; final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>(); for (RemoteAnimationTarget target : openingTargets) { - adapters.add(createOpenCloseAnimationAdapter(target, animationProvider, - openingWholeScreenBounds)); + final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target, + animationProvider, openingWholeScreenBounds); + if (isOpening) { + adapter.overrideLayer(offsetLayer++); + } + adapters.add(adapter); } for (RemoteAnimationTarget target : closingTargets) { - adapters.add(createOpenCloseAnimationAdapter(target, animationProvider, - closingWholeScreenBounds)); + final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target, + animationProvider, closingWholeScreenBounds); + if (!isOpening) { + adapter.overrideLayer(offsetLayer++); + } + adapters.add(adapter); } return adapters; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 9e5359332055..48dd1fe3cb7e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -1329,8 +1329,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Once the pending enter transition got merged, make sure to bring divider bar visible and // clear the pending transition from cache to prevent mess-up the following state. if (transition == mSplitTransitions.mPendingEnter) { - finishEnterSplitScreen(null); + final SurfaceControl.Transaction t = mTransactionPool.acquire(); + finishEnterSplitScreen(t); mSplitTransitions.mPendingEnter = null; + t.apply(); + mTransactionPool.release(t); } } diff --git a/media/java/android/media/tv/interactive/AppLinkInfo.java b/media/java/android/media/tv/interactive/AppLinkInfo.java index cd201f79ed41..0eb6fa8996d6 100644 --- a/media/java/android/media/tv/interactive/AppLinkInfo.java +++ b/media/java/android/media/tv/interactive/AppLinkInfo.java @@ -18,6 +18,7 @@ package android.media.tv.interactive; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; @@ -25,8 +26,7 @@ import android.os.Parcelable; * App link information used by TV interactive app to launch Android apps. */ public final class AppLinkInfo implements Parcelable { - private @NonNull String mPackageName; - private @NonNull String mClassName; + private @NonNull ComponentName mComponentName; private @Nullable String mUriScheme; private @Nullable String mUriHost; private @Nullable String mUriPrefix; @@ -41,12 +41,11 @@ public final class AppLinkInfo implements Parcelable { @Nullable String uriScheme, @Nullable String uriHost, @Nullable String uriPrefix) { - this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mPackageName); - this.mClassName = className; + NonNull.class, null, packageName); com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mClassName); + NonNull.class, null, className); + this.mComponentName = new ComponentName(packageName, className); this.mUriScheme = uriScheme; this.mUriHost = uriHost; this.mUriPrefix = uriPrefix; @@ -57,7 +56,7 @@ public final class AppLinkInfo implements Parcelable { */ @NonNull public String getPackageName() { - return mPackageName; + return mComponentName.getPackageName(); } /** @@ -65,7 +64,7 @@ public final class AppLinkInfo implements Parcelable { */ @NonNull public String getClassName() { - return mClassName; + return mComponentName.getClassName(); } /** @@ -95,8 +94,8 @@ public final class AppLinkInfo implements Parcelable { @Override public String toString() { return "AppLinkInfo { " - + "packageName = " + mPackageName + ", " - + "className = " + mClassName + ", " + + "packageName = " + mComponentName.getPackageName() + ", " + + "className = " + mComponentName.getClassName() + ", " + "uriScheme = " + mUriScheme + ", " + "uriHost = " + mUriHost + ", " + "uriPrefix = " + mUriPrefix @@ -105,8 +104,8 @@ public final class AppLinkInfo implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(mPackageName); - dest.writeString(mClassName); + dest.writeString(mComponentName.getPackageName()); + dest.writeString(mComponentName.getClassName()); dest.writeString(mUriScheme); dest.writeString(mUriHost); dest.writeString(mUriPrefix); @@ -124,12 +123,11 @@ public final class AppLinkInfo implements Parcelable { String uriHost = in.readString(); String uriPrefix = in.readString(); - this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mPackageName); - this.mClassName = className; + NonNull.class, null, packageName); com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mClassName); + NonNull.class, null, className); + this.mComponentName = new ComponentName(packageName, className); this.mUriScheme = uriScheme; this.mUriHost = uriHost; this.mUriPrefix = uriPrefix; @@ -174,28 +172,10 @@ public final class AppLinkInfo implements Parcelable { } /** - * Sets package name of the App link. - */ - @NonNull - public Builder setPackageName(@NonNull String value) { - mPackageName = value; - return this; - } - - /** - * Sets app name of the App link. - */ - @NonNull - public Builder setClassName(@NonNull String value) { - mClassName = value; - return this; - } - - /** * Sets URI scheme of the App link. */ @NonNull - public Builder setUriScheme(@Nullable String value) { + public Builder setUriScheme(@NonNull String value) { mUriScheme = value; return this; } @@ -204,7 +184,7 @@ public final class AppLinkInfo implements Parcelable { * Sets URI host of the App link. */ @NonNull - public Builder setUriHost(@Nullable String value) { + public Builder setUriHost(@NonNull String value) { mUriHost = value; return this; } @@ -213,7 +193,7 @@ public final class AppLinkInfo implements Parcelable { * Sets URI prefix of the App link. */ @NonNull - public Builder setUriPrefix(@Nullable String value) { + public Builder setUriPrefix(@NonNull String value) { mUriPrefix = value; return this; } diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java index f75aa56813ab..b6db4cfbe910 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -760,7 +760,12 @@ public final class TvInteractiveAppManager { } /** - * Registers app link info. + * Registers an Android application link info record which can be used to launch the specific + * Android application by TV interactive App RTE. + * + * @param tvIAppServiceId The ID of TV interactive service which the command to be sent to. The + * ID can be found in {@link TvInputInfo#getId()}. + * @param appLinkInfo The Android application link info record to be registered. */ public void registerAppLinkInfo( @NonNull String tvIAppServiceId, @NonNull AppLinkInfo appLinkInfo) { @@ -772,7 +777,12 @@ public final class TvInteractiveAppManager { } /** - * Unregisters app link info. + * Unregisters an Android application link info record which can be used to launch the specific + * Android application by TV interactive App RTE. + * + * @param tvIAppServiceId The ID of TV interactive service which the command to be sent to. The + * ID can be found in {@link TvInputInfo#getId()}. + * @param appLinkInfo The Android application link info record to be unregistered. */ public void unregisterAppLinkInfo( @NonNull String tvIAppServiceId, @NonNull AppLinkInfo appLinkInfo) { @@ -1813,8 +1823,8 @@ public final class TvInteractiveAppManager { } /** - * This is called when {@link TvIAppService.Session#notifyTeletextAppStateChanged} is - * called. + * This is called when {@link TvInteractiveAppService.Session#notifyTeletextAppStateChanged} + * is called. * * @param session A {@link TvInteractiveAppManager.Session} associated with this callback. * @param state the current state. diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java index 52b00b7b43e5..bb6edf54a7ff 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -19,6 +19,7 @@ package android.media.tv.interactive; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.annotation.StringDef; import android.annotation.SuppressLint; import android.app.ActivityManager; @@ -76,15 +77,14 @@ public abstract class TvInteractiveAppService extends Service { private static final int DETACH_MEDIA_VIEW_TIMEOUT_MS = 5000; - // TODO: cleanup and unhide APIs. - /** * This is the interface name that a service implementing a TV Interactive App service should * say that it supports -- that is, this is the action it uses for its intent filter. To be * supported, the service must also require the - * android.Manifest.permission#BIND_TV_INTERACTIVE_APP permission so that other applications - * cannot abuse it. + * {@link android.Manifest.permission#BIND_TV_INTERACTIVE_APP} permission so that other + * applications cannot abuse it. */ + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvInteractiveAppService"; @@ -244,13 +244,13 @@ public abstract class TvInteractiveAppService extends Service { public abstract void onPrepare(@TvInteractiveAppInfo.InteractiveAppType int type); /** - * Registers App link info. + * Called when a request to register an Android application link info record is received. */ public void onRegisterAppLinkInfo(@NonNull AppLinkInfo appLinkInfo) { } /** - * Unregisters App link info. + * Called when a request to unregister an Android application link info record is received. */ public void onUnregisterAppLinkInfo(@NonNull AppLinkInfo appLinkInfo) { } @@ -383,7 +383,7 @@ public abstract class TvInteractiveAppService extends Service { } /** - * Resets TvIAppService session. + * Resets TvInteractiveAppService session. */ public void onResetInteractiveApp() { } diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java index 50a208344c3a..3b7089030255 100644 --- a/media/java/android/media/tv/tuner/Lnb.java +++ b/media/java/android/media/tv/tuner/Lnb.java @@ -167,10 +167,10 @@ public class Lnb implements AutoCloseable { private Lnb() {} - void setCallbackAndOwner(Executor executor, @Nullable LnbCallback callback, Tuner tuner) { + void setCallbackAndOwner(Tuner tuner, Executor executor, @Nullable LnbCallback callback) { synchronized (mCallbackLock) { if (callback != null && executor != null) { - addCallback(callback, executor); + addCallback(executor, callback); } } setOwner(tuner); @@ -179,12 +179,12 @@ public class Lnb implements AutoCloseable { /** * Adds LnbCallback * - * @param callback the callback to receive notifications from LNB. * @param executor the executor on which callback will be invoked. Cannot be null. + * @param callback the callback to receive notifications from LNB. */ - public void addCallback(@NonNull LnbCallback callback, @NonNull Executor executor) { - Objects.requireNonNull(callback, "callback must not be null"); + public void addCallback(@NonNull Executor executor, @NonNull LnbCallback callback) { Objects.requireNonNull(executor, "executor must not be null"); + Objects.requireNonNull(callback, "callback must not be null"); synchronized (mCallbackLock) { mCallbackMap.put(callback, executor); } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 1e32cadc2748..ef0270b5414c 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -62,7 +62,9 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.util.Log; + import com.android.internal.util.FrameworkStatsLog; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -2147,12 +2149,12 @@ public class Tuner implements AutoCloseable { Objects.requireNonNull(executor, "executor must not be null"); Objects.requireNonNull(cb, "LnbCallback must not be null"); if (mLnb != null) { - mLnb.setCallbackAndOwner(executor, cb, this); + mLnb.setCallbackAndOwner(this, executor, cb); return mLnb; } if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB, mLnbLock) && mLnb != null) { - mLnb.setCallbackAndOwner(executor, cb, this); + mLnb.setCallbackAndOwner(this, executor, cb); setLnb(mLnb); return mLnb; } @@ -2186,7 +2188,7 @@ public class Tuner implements AutoCloseable { mLnbHandle = null; } mLnb = newLnb; - mLnb.setCallbackAndOwner(executor, cb, this); + mLnb.setCallbackAndOwner(this, executor, cb); setLnb(mLnb); } return mLnb; diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java index 72243f9e87d9..eba51c11487e 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java @@ -511,7 +511,6 @@ public class EthernetManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) - @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) public void updateConfiguration( @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index e524405a39d5..042fef23cbe6 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1572,4 +1572,10 @@ <!-- Content description for a default user icon. [CHAR LIMIT=NONE] --> <string name="default_user_icon_description">Default user icon</string> + <!-- Title for the 'physical keyboard' settings screen. [CHAR LIMIT=35] --> + <string name="physical_keyboard_title">Physical keyboard</string> + <!-- Title for the keyboard layout preference dialog. [CHAR LIMIT=35] --> + <string name="keyboard_layout_dialog_title">Choose keyboard layout</string> + <!-- Label of the default keyboard layout. [CHAR LIMIT=35] --> + <string name="keyboard_layout_default_label">Default</string> </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 1c9d9cf376f1..3d91c5aceeed 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -285,6 +285,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> public void disconnect() { synchronized (mProfileLock) { + if (getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { + for (CachedBluetoothDevice member : getMemberDevice()) { + Log.d(TAG, "Disconnect the member(" + member.getAddress() + ")"); + member.disconnect(); + } + } mDevice.disconnect(); } // Disconnect PBAP server in case its connected @@ -399,6 +405,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } mDevice.connect(); + if (getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { + for (CachedBluetoothDevice member : getMemberDevice()) { + Log.d(TAG, "connect the member(" + member.getAddress() + ")"); + member.connect(); + } + } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java index 4ab6542d567a..9ef6bdf0fb41 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java @@ -43,6 +43,31 @@ public class WifiUtils { private static final int INVALID_RSSI = -127; /** + * The intent action shows Wi-Fi dialog to connect Wi-Fi network. + * <p> + * Input: The calling package should put the chosen + * com.android.wifitrackerlib.WifiEntry#getKey() to a string extra in the request bundle into + * the {@link #EXTRA_CHOSEN_WIFI_ENTRY_KEY}. + * <p> + * Output: Nothing. + */ + @VisibleForTesting + static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG"; + + /** + * Specify a key that indicates the WifiEntry to be configured. + */ + @VisibleForTesting + static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; + + /** + * The lookup key for a boolean that indicates whether a chosen WifiEntry request to connect to. + * {@code true} means a chosen WifiEntry request to connect to. + */ + @VisibleForTesting + static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller"; + + /** * The intent action shows network details settings to allow configuration of Wi-Fi. * <p> * In some cases, a matching Activity may not exist, so ensure you @@ -325,6 +350,19 @@ public class WifiUtils { } /** + * Returns the Intent for Wi-Fi dialog. + * + * @param key The Wi-Fi entry key + * @param connectForCaller True if a chosen WifiEntry request to connect to + */ + public static Intent getWifiDialogIntent(String key, boolean connectForCaller) { + final Intent intent = new Intent(ACTION_WIFI_DIALOG); + intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, key); + intent.putExtra(EXTRA_CONNECT_FOR_CALLER, connectForCaller); + return intent; + } + + /** * Returns the Intent for Wi-Fi network details settings. * * @param key The Wi-Fi entry key diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java index 1d08711715c3..d988111c29d5 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AvatarPhotoControllerTest.java @@ -89,6 +89,10 @@ public class AvatarPhotoControllerTest { @After public void tearDown() { + String[] entries = mImagesDir.list(); + for (String entry : entries) { + new File(mImagesDir, entry).delete(); + } mImagesDir.delete(); } @@ -233,7 +237,8 @@ public class AvatarPhotoControllerTest { public void internalCropUsedIfNoSystemCropperFound() throws IOException { when(mMockAvatarUi.startSystemActivityForResult(any(), anyInt())).thenReturn(false); - new File(mImagesDir, "file.txt").createNewFile(); + File file = new File(mImagesDir, "file.txt"); + saveBitmapToFile(file); Intent intent = new Intent(); intent.setData(Uri.parse( @@ -241,10 +246,6 @@ public class AvatarPhotoControllerTest { mController.onActivityResult( REQUEST_CODE_TAKE_PHOTO, Activity.RESULT_OK, intent); - Intent startIntent = verifyStartSystemActivityForResult( - "com.android.camera.action.CROP", REQUEST_CODE_CROP_PHOTO); - assertThat(startIntent.getData()).isNotEqualTo(mTakePhotoUri); - verify(mMockAvatarUi, timeout(TIMEOUT_MILLIS)).returnUriResult(mCropPhotoUri); InputStream imageStream = mContext.getContentResolver().openInputStream(mCropPhotoUri); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java index e7b3fe9ab8da..69561055ff7f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java @@ -156,6 +156,27 @@ public class WifiUtilsTest { } @Test + public void getWifiDialogIntent_returnsCorrectValues() { + String key = "test_key"; + + // Test that connectForCaller is true. + Intent intent = WifiUtils.getWifiDialogIntent(key, true /* connectForCaller */); + + assertThat(intent.getAction()).isEqualTo(WifiUtils.ACTION_WIFI_DIALOG); + assertThat(intent.getStringExtra(WifiUtils.EXTRA_CHOSEN_WIFI_ENTRY_KEY)).isEqualTo(key); + assertThat(intent.getBooleanExtra(WifiUtils.EXTRA_CONNECT_FOR_CALLER, true)) + .isEqualTo(true /* connectForCaller */); + + // Test that connectForCaller is false. + intent = WifiUtils.getWifiDialogIntent(key, false /* connectForCaller */); + + assertThat(intent.getAction()).isEqualTo(WifiUtils.ACTION_WIFI_DIALOG); + assertThat(intent.getStringExtra(WifiUtils.EXTRA_CHOSEN_WIFI_ENTRY_KEY)).isEqualTo(key); + assertThat(intent.getBooleanExtra(WifiUtils.EXTRA_CONNECT_FOR_CALLER, true)) + .isEqualTo(false /* connectForCaller */); + } + + @Test public void getWifiDetailsSettingsIntent_returnsCorrectValues() { final String key = "test_key"; diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index fa3360cd31f6..cbd71c02baf4 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -328,7 +328,5 @@ public class SecureSettingsValidators { return true; }); VALIDATORS.put(Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.FAST_PAIR_SCAN_ENABLED, BOOLEAN_VALIDATOR); - } } diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 7f8b2f51754c..e24b2d6c6aa9 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -794,7 +794,7 @@ android:noHistory="true" android:showForAllUsers="true" android:finishOnTaskLaunch="true" - android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden" + android:configChanges="screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden" android:visibleToInstantApps="true"> </activity> @@ -805,7 +805,7 @@ android:showForAllUsers="true" android:finishOnTaskLaunch="true" android:launchMode="singleInstance" - android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden" + android:configChanges="screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden" android:visibleToInstantApps="true"> </activity> diff --git a/packages/SystemUI/animation/res/values/ids.xml b/packages/SystemUI/animation/res/values/ids.xml index ef60a248f79a..4e9a4be0060e 100644 --- a/packages/SystemUI/animation/res/values/ids.xml +++ b/packages/SystemUI/animation/res/values/ids.xml @@ -15,5 +15,14 @@ limitations under the License. --> <resources> + <!-- DialogLaunchAnimator --> <item type="id" name="launch_animation_running"/> + + <!-- ViewBoundsAnimator --> + <item type="id" name="tag_animator"/> + <item type="id" name="tag_layout_listener"/> + <item type="id" name="tag_override_bottom"/> + <item type="id" name="tag_override_left"/> + <item type="id" name="tag_override_right"/> + <item type="id" name="tag_override_top"/> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewBoundAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewBoundAnimator.kt new file mode 100644 index 000000000000..5593fdfe5f51 --- /dev/null +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewBoundAnimator.kt @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.animation + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.ObjectAnimator +import android.animation.PropertyValuesHolder +import android.util.IntProperty +import android.view.View +import android.view.ViewGroup +import android.view.animation.Interpolator + +/** + * A class that allows changes in bounds within a view hierarchy to animate seamlessly between the + * start and end state. + */ +class ViewBoundAnimator { + // TODO(b/221418522): make this private once it can't be passed as an arg anymore. + enum class Bound(val label: String, val overrideTag: Int) { + LEFT("left", R.id.tag_override_left) { + override fun setValue(view: View, value: Int) { + view.left = value + } + + override fun getValue(view: View): Int { + return view.left + } + }, + TOP("top", R.id.tag_override_top) { + override fun setValue(view: View, value: Int) { + view.top = value + } + + override fun getValue(view: View): Int { + return view.top + } + }, + RIGHT("right", R.id.tag_override_right) { + override fun setValue(view: View, value: Int) { + view.right = value + } + + override fun getValue(view: View): Int { + return view.right + } + }, + BOTTOM("bottom", R.id.tag_override_bottom) { + override fun setValue(view: View, value: Int) { + view.bottom = value + } + + override fun getValue(view: View): Int { + return view.bottom + } + }; + + abstract fun setValue(view: View, value: Int) + abstract fun getValue(view: View): Int + } + + companion object { + /** Default values for the animation. These can all be overridden at call time. */ + private const val DEFAULT_DURATION = 500L + private val DEFAULT_INTERPOLATOR = Interpolators.EMPHASIZED + private val DEFAULT_BOUNDS = setOf(Bound.LEFT, Bound.TOP, Bound.RIGHT, Bound.BOTTOM) + + /** The properties used to animate the view bounds. */ + private val PROPERTIES = mapOf( + Bound.LEFT to createViewProperty(Bound.LEFT), + Bound.TOP to createViewProperty(Bound.TOP), + Bound.RIGHT to createViewProperty(Bound.RIGHT), + Bound.BOTTOM to createViewProperty(Bound.BOTTOM) + ) + + private fun createViewProperty(bound: Bound): IntProperty<View> { + return object : IntProperty<View>(bound.label) { + override fun setValue(view: View, value: Int) { + setBound(view, bound, value) + } + + override fun get(view: View): Int { + return getBound(view, bound) ?: bound.getValue(view) + } + } + } + + /** + * Instruct the animator to watch for changes to the layout of [rootView] and its children + * and animate them. The animation can be limited to a subset of [bounds]. It uses the + * given [interpolator] and [duration]. + * + * If a new layout change happens while an animation is already in progress, the animation + * is updated to continue from the current values to the new end state. + * + * The animator continues to respond to layout changes until [stopAnimating] is called. + * + * Successive calls to this method override the previous settings ([interpolator] and + * [duration]). The changes take effect on the next animation. + * + * TODO(b/221418522): remove the ability to select which bounds to animate and always + * animate all of them. + */ + @JvmOverloads + fun animate( + rootView: View, + bounds: Set<Bound> = DEFAULT_BOUNDS, + interpolator: Interpolator = DEFAULT_INTERPOLATOR, + duration: Long = DEFAULT_DURATION + ) { + animate(rootView, bounds, interpolator, duration, false /* ephemeral */) + } + + /** + * Like [animate], but only takes effect on the next layout update, then unregisters itself + * once the first animation is complete. + * + * TODO(b/221418522): remove the ability to select which bounds to animate and always + * animate all of them. + */ + @JvmOverloads + fun animateNextUpdate( + rootView: View, + bounds: Set<Bound> = DEFAULT_BOUNDS, + interpolator: Interpolator = DEFAULT_INTERPOLATOR, + duration: Long = DEFAULT_DURATION + ) { + animate(rootView, bounds, interpolator, duration, true /* ephemeral */) + } + + private fun animate( + rootView: View, + bounds: Set<Bound>, + interpolator: Interpolator, + duration: Long, + ephemeral: Boolean + ) { + val listener = createListener(bounds, interpolator, duration, ephemeral) + recursivelyAddListener(rootView, listener) + } + + /** + * Instruct the animator to stop watching for changes to the layout of [rootView] and its + * children. + * + * Any animations already in progress continue until their natural conclusion. + */ + fun stopAnimating(rootView: View) { + val listener = rootView.getTag(R.id.tag_layout_listener) + if (listener != null && listener is View.OnLayoutChangeListener) { + rootView.setTag(R.id.tag_layout_listener, null /* tag */) + rootView.removeOnLayoutChangeListener(listener) + } + + if (rootView is ViewGroup) { + for (i in 0 until rootView.childCount) { + stopAnimating(rootView.getChildAt(i)) + } + } + } + + private fun createListener( + bounds: Set<Bound>, + interpolator: Interpolator, + duration: Long, + ephemeral: Boolean + ): View.OnLayoutChangeListener { + return object : View.OnLayoutChangeListener { + override fun onLayoutChange( + view: View?, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + if (view == null) return + + val startLeft = getBound(view, Bound.LEFT) ?: oldLeft + val startTop = getBound(view, Bound.TOP) ?: oldTop + val startRight = getBound(view, Bound.RIGHT) ?: oldRight + val startBottom = getBound(view, Bound.BOTTOM) ?: oldBottom + + (view.getTag(R.id.tag_animator) as? ObjectAnimator)?.cancel() + + if (view.visibility == View.GONE || view.visibility == View.INVISIBLE) { + setBound(view, Bound.LEFT, left) + setBound(view, Bound.TOP, top) + setBound(view, Bound.RIGHT, right) + setBound(view, Bound.BOTTOM, bottom) + return + } + + val startValues = mapOf( + Bound.LEFT to startLeft, + Bound.TOP to startTop, + Bound.RIGHT to startRight, + Bound.BOTTOM to startBottom + ) + val endValues = mapOf( + Bound.LEFT to left, + Bound.TOP to top, + Bound.RIGHT to right, + Bound.BOTTOM to bottom + ) + + val boundsToAnimate = bounds.toMutableSet() + if (left == startLeft) boundsToAnimate.remove(Bound.LEFT) + if (top == startTop) boundsToAnimate.remove(Bound.TOP) + if (right == startRight) boundsToAnimate.remove(Bound.RIGHT) + if (bottom == startBottom) boundsToAnimate.remove(Bound.BOTTOM) + + if (boundsToAnimate.isNotEmpty()) { + startAnimation( + view, + boundsToAnimate, + startValues, + endValues, + interpolator, + duration, + ephemeral + ) + } + } + } + } + + private fun recursivelyAddListener(view: View, listener: View.OnLayoutChangeListener) { + // Make sure that only one listener is active at a time. + val oldListener = view.getTag(R.id.tag_layout_listener) + if (oldListener != null && oldListener is View.OnLayoutChangeListener) { + view.removeOnLayoutChangeListener(oldListener) + } + + view.addOnLayoutChangeListener(listener) + view.setTag(R.id.tag_layout_listener, listener) + if (view is ViewGroup) { + for (i in 0 until view.childCount) { + recursivelyAddListener(view.getChildAt(i), listener) + } + } + } + + private fun getBound(view: View, bound: Bound): Int? { + return view.getTag(bound.overrideTag) as? Int + } + + private fun setBound(view: View, bound: Bound, value: Int) { + view.setTag(bound.overrideTag, value) + bound.setValue(view, value) + } + + /** + * Initiates the animation of a single bound by creating the animator, registering it with + * the [view], and starting it. If [ephemeral], the layout change listener is unregistered + * at the end of the animation, so no more animations happen. + */ + private fun startAnimation( + view: View, + bounds: Set<Bound>, + startValues: Map<Bound, Int>, + endValues: Map<Bound, Int>, + interpolator: Interpolator, + duration: Long, + ephemeral: Boolean + ) { + val propertyValuesHolders = buildList { + bounds.forEach { bound -> + add( + PropertyValuesHolder.ofInt( + PROPERTIES[bound], + startValues.getValue(bound), + endValues.getValue(bound) + ) + ) + } + }.toTypedArray() + + val animator = ObjectAnimator.ofPropertyValuesHolder(view, *propertyValuesHolders) + animator.interpolator = interpolator + animator.duration = duration + animator.addListener(object : AnimatorListenerAdapter() { + var cancelled = false + + override fun onAnimationEnd(animation: Animator) { + view.setTag(R.id.tag_animator, null /* tag */) + bounds.forEach { view.setTag(it.overrideTag, null /* tag */) } + + // When an animation is cancelled, a new one might be taking over. We shouldn't + // unregister the listener yet. + if (ephemeral && !cancelled) { + val listener = view.getTag(R.id.tag_layout_listener) + if (listener != null && listener is View.OnLayoutChangeListener) { + view.setTag(R.id.tag_layout_listener, null /* tag */) + view.removeOnLayoutChangeListener(listener) + } + } + } + + override fun onAnimationCancel(animation: Animator?) { + cancelled = true + } + }) + + bounds.forEach { bound -> setBound(view, bound, startValues.getValue(bound)) } + + view.setTag(R.id.tag_animator, animator) + animator.start() + } + } +} diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 637569830465..625ffd3aa3ec 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -17,13 +17,14 @@ */ --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <!-- Keyguard PIN pad styles --> <style name="Keyguard.TextView" parent="@android:style/Widget.DeviceDefault.TextView"> <item name="android:textSize">@dimen/kg_status_line_font_size</item> </style> <style name="Keyguard.TextView.EmergencyButton" parent="Theme.SystemUI"> - <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> + <item name="android:textColor">?androidprv:attr/textColorOnAccent</item> <item name="android:textSize">14dp</item> <item name="android:background">@drawable/kg_emergency_button_background</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml index 9ad01528686e..f030f3130be4 100644 --- a/packages/SystemUI/res/layout/media_session_view.xml +++ b/packages/SystemUI/res/layout/media_session_view.xml @@ -44,6 +44,7 @@ android:background="@drawable/qs_media_scrim" /> + <!-- Guideline for output switcher --> <androidx.constraintlayout.widget.Guideline android:id="@+id/center_vertical_guideline" android:layout_width="wrap_content" @@ -51,6 +52,14 @@ android:orientation="vertical" app:layout_constraintGuide_percent="0.6" /> + <!-- Guideline for action buttons (collapsed view only) --> + <androidx.constraintlayout.widget.Guideline + android:id="@+id/action_button_guideline" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintGuide_end="@dimen/qs_media_session_collapsed_guideline" /> + <!-- App icon --> <com.android.internal.widget.CachingIconView android:id="@+id/icon" @@ -118,15 +127,7 @@ android:singleLine="true" android:textSize="16sp" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="20dp" - android:layout_marginStart="@dimen/qs_media_padding" - android:layout_marginEnd="@dimen/qs_media_padding" - app:layout_constrainedWidth="true" - app:layout_constraintTop_toBottomOf="@id/icon" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/actionPlayPause" - app:layout_constraintHorizontal_bias="0" /> + android:layout_height="wrap_content" /> <!-- Artist name --> <TextView @@ -136,15 +137,7 @@ style="@style/MediaPlayer.Subtitle" android:textSize="14sp" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/qs_media_padding" - app:layout_constrainedWidth="true" - android:layout_marginTop="0dp" - app:layout_constraintTop_toBottomOf="@id/header_title" - app:layout_constraintStart_toStartOf="@id/header_title" - app:layout_constraintEnd_toStartOf="@id/actionPlayPause" - app:layout_constraintBottom_toBottomOf="@id/actionPlayPause" - app:layout_constraintHorizontal_bias="0" /> + android:layout_height="wrap_content" /> <ImageButton android:id="@+id/actionPlayPause" @@ -153,9 +146,33 @@ android:layout_height="48dp" android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginEnd="@dimen/qs_media_padding" - android:layout_marginTop="0dp" - android:layout_marginBottom="0dp" /> + /> + + <!-- See comment in media_session_collapsed.xml for how these barriers are used --> + <androidx.constraintlayout.widget.Barrier + android:id="@+id/media_action_barrier" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintTop_toBottomOf="@id/header_title" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:barrierDirection="start" + app:constraint_referenced_ids="actionPrev,media_progress_bar,actionNext,action0,action1,action2,action3,action4" + /> + <androidx.constraintlayout.widget.Barrier + android:id="@+id/media_action_barrier_end" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintBottom_toBottomOf="parent" + app:barrierDirection="end" + app:constraint_referenced_ids="actionPrev,media_progress_bar,actionNext,action0,action1,action2,action3,action4" + app:layout_constraintStart_toStartOf="parent" + /> + <!-- Button visibility will be controlled in code --> <ImageButton android:id="@+id/actionPrev" style="@style/MediaPlayer.SessionAction" @@ -163,10 +180,9 @@ android:layout_height="48dp" android:layout_marginStart="4dp" android:layout_marginEnd="0dp" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintHorizontal_chainStyle="packed" /> + /> <!-- Seek Bar --> <!-- As per Material Design on Bidirectionality, this is forced to LTR in code --> @@ -174,12 +190,12 @@ android:id="@+id/media_progress_bar" style="@style/MediaPlayer.ProgressBar" android:layout_width="0dp" - android:layout_height="wrap_content" + android:layout_height="48dp" android:paddingTop="@dimen/qs_media_session_enabled_seekbar_vertical_padding" android:paddingBottom="12dp" android:maxHeight="@dimen/qs_media_enabled_seekbar_height" android:splitTrack="false" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" /> @@ -191,29 +207,58 @@ android:layout_height="48dp" android:layout_marginStart="0dp" android:layout_marginEnd="@dimen/qs_media_action_spacing" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" /> <ImageButton - android:id="@+id/actionStart" + android:id="@+id/action0" style="@style/MediaPlayer.SessionAction" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginStart="@dimen/qs_media_action_spacing" android:layout_marginEnd="@dimen/qs_media_action_spacing" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp"/> + + <ImageButton + android:id="@+id/action1" + style="@style/MediaPlayer.SessionAction" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_action_spacing" + android:layout_marginEnd="4dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" /> <ImageButton - android:id="@+id/actionEnd" + android:id="@+id/action2" style="@style/MediaPlayer.SessionAction" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginStart="@dimen/qs_media_action_spacing" android:layout_marginEnd="4dp" - android:layout_marginBottom="0dp" - android:layout_marginTop="0dp" - app:layout_constraintHorizontal_chainStyle="packed" /> + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp" /> + + <ImageButton + android:id="@+id/action3" + style="@style/MediaPlayer.SessionAction" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_action_spacing" + android:layout_marginEnd="4dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp" /> + + <ImageButton + android:id="@+id/action4" + style="@style/MediaPlayer.SessionAction" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_action_spacing" + android:layout_marginEnd="4dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp" /> <!-- Long press menu --> <TextView diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml index c9906053b4cb..f5c0509dbf5b 100644 --- a/packages/SystemUI/res/values-sw600dp-port/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp-port/dimens.xml @@ -15,7 +15,7 @@ ~ limitations under the License. --> <resources> - <dimen name="notification_panel_margin_horizontal">60dp</dimen> + <dimen name="notification_panel_margin_horizontal">48dp</dimen> <dimen name="status_view_margin_horizontal">62dp</dimen> <dimen name="keyguard_clock_top_margin">40dp</dimen> <dimen name="keyguard_status_view_bottom_margin">40dp</dimen> diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml index e5f502f95290..44f8f3aee9ab 100644 --- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml @@ -21,8 +21,11 @@ for different hardware and product builds. --> <resources> <dimen name="status_view_margin_horizontal">124dp</dimen> - <dimen name="notification_panel_margin_horizontal">120dp</dimen> <dimen name="keyguard_clock_top_margin">80dp</dimen> <dimen name="keyguard_status_view_bottom_margin">80dp</dimen> <dimen name="bouncer_user_switcher_y_trans">90dp</dimen> + + <dimen name="notification_panel_margin_horizontal">96dp</dimen> + <dimen name="notification_side_paddings">40dp</dimen> + <dimen name="notification_section_divider_height">16dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index c64beb58449c..52ec51629116 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -139,7 +139,7 @@ <!-- Height of a heads up notification in the status bar --> <dimen name="notification_max_heads_up_height_increased">188dp</dimen> - <!-- Side padding on the lockscreen on the side of notifications --> + <!-- Side padding on the side of notifications --> <dimen name="notification_side_paddings">16dp</dimen> <!-- padding between the heads up and the statusbar --> @@ -983,6 +983,7 @@ <dimen name="qs_media_seekbar_progress_amplitude">1.5dp</dimen> <dimen name="qs_media_seekbar_progress_phase">8dp</dimen> <dimen name="qs_media_seekbar_progress_stroke_width">2dp</dimen> + <dimen name="qs_media_session_collapsed_guideline">144dp</dimen> <!-- Size of Smartspace media recommendations cards in the QSPanel carousel --> <dimen name="qs_aa_media_rec_album_size_collapsed">72dp</dimen> @@ -1366,9 +1367,6 @@ <dimen name="dream_overlay_status_icon_margin">8dp</dimen> <dimen name="dream_overlay_status_bar_icon_size"> @*android:dimen/status_bar_system_icon_size</dimen> - <!-- Height of the area at the top of the dream overlay to allow dragging down the notifications - shade. --> - <dimen name="dream_overlay_notifications_drag_area_height">100dp</dimen> <dimen name="dream_overlay_camera_mic_off_indicator_size">8dp</dimen> <dimen name="dream_overlay_notification_indicator_size">6dp</dimen> diff --git a/packages/SystemUI/res/xml/media_session_collapsed.xml b/packages/SystemUI/res/xml/media_session_collapsed.xml index c6e18a6f8740..f00e03116337 100644 --- a/packages/SystemUI/res/xml/media_session_collapsed.xml +++ b/packages/SystemUI/res/xml/media_session_collapsed.xml @@ -19,6 +19,13 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> <Constraint + android:id="@+id/media_action_barrier" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintStart_toEndOf="@id/action_button_guideline" /> + + <Constraint android:id="@+id/album_art" android:layout_width="match_parent" android:layout_height="@dimen/qs_media_session_height_collapsed" @@ -28,33 +35,73 @@ app:layout_constraintBottom_toBottomOf="parent" /> <Constraint + android:id="@+id/header_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:layout_marginStart="@dimen/qs_media_padding" + android:layout_marginEnd="@dimen/qs_media_padding" + app:layout_constraintEnd_toStartOf="@id/action_button_guideline" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toBottomOf="@id/icon" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintHorizontal_bias="0" /> + <Constraint + android:id="@+id/header_artist" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/qs_media_padding" + android:layout_marginTop="0dp" + app:layout_constraintEnd_toStartOf="@id/action_button_guideline" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toBottomOf="@id/header_title" + app:layout_constraintStart_toStartOf="@id/header_title" + app:layout_constraintVertical_bias="0" + app:layout_constraintHorizontal_bias="0" /> + + <Constraint android:id="@+id/actionPlayPause" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginEnd="@dimen/qs_media_padding" - app:layout_constraintStart_toEndOf="@id/actionEnd" + android:layout_marginBottom="@dimen/qs_media_padding" + app:layout_constraintVertical_bias="1" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" - app:layout_constraintBottom_toBottomOf="parent" /> + app:layout_constraintStart_toEndOf="@id/media_action_barrier_end" /> + <!-- + There will only be 3 action buttons shown at most in this layout (controlled in code). + Play/Pause should always be at the end, but the other buttons should remain in the same order + when in RTL. + This is accomplished by setting two barriers at the start and end of the small buttons, + anchored to a guideline set at 3x button width from the end. The text and play/pause button are + positioned relative to the barriers, and the small buttons use right/left constraints to stay + in the correct order inside the barriers. + --> <Constraint android:id="@+id/actionPrev" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" app:layout_constraintHorizontal_bias="1" + app:layout_constraintVertical_bias="1" app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintStart_toEndOf="@id/header_artist" - app:layout_constraintEnd_toStartOf="@id/media_progress_bar" + app:layout_constraintRight_toLeftOf="@id/media_progress_bar" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/media_seamless" /> + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintLeft_toRightOf="@id/media_action_barrier" /> <Constraint android:id="@+id/media_progress_bar" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/qs_media_padding" android:visibility="gone" - app:layout_constraintStart_toEndOf="@id/actionPrev" - app:layout_constraintEnd_toStartOf="@id/actionNext" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/actionPrev" + app:layout_constraintRight_toLeftOf="@id/actionNext" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> @@ -62,29 +109,70 @@ android:id="@+id/actionNext" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/media_progress_bar" - app:layout_constraintEnd_toStartOf="@id/actionStart" + android:layout_marginBottom="@dimen/qs_media_padding" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/media_progress_bar" + app:layout_constraintRight_toLeftOf="@id/action0" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/media_seamless" /> + + <Constraint + android:id="@+id/action0" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:visibility="gone" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/actionNext" + app:layout_constraintRight_toLeftOf="@id/action1" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/media_seamless" /> + + <Constraint + android:id="@+id/action1" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:visibility="gone" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action0" + app:layout_constraintRight_toLeftOf="@id/action2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> <Constraint - android:id="@+id/actionStart" + android:id="@+id/action2" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:visibility="gone" - app:layout_constraintStart_toEndOf="@id/actionNext" - app:layout_constraintEnd_toStartOf="@id/actionEnd" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action1" + app:layout_constraintRight_toLeftOf="@id/action3" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> <Constraint - android:id="@+id/actionEnd" + android:id="@+id/action3" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:visibility="gone" - app:layout_constraintStart_toEndOf="@id/actionStart" - app:layout_constraintEnd_toStartOf="@id/actionPlayPause" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action2" + app:layout_constraintRight_toLeftOf="@id/action4" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> -</ConstraintSet>
\ No newline at end of file + <Constraint + android:id="@+id/action4" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:visibility="gone" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action3" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintRight_toLeftOf="@id/media_action_barrier_end" /> +</ConstraintSet> diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml index 18ec7aa4cab4..10da70447ec0 100644 --- a/packages/SystemUI/res/xml/media_session_expanded.xml +++ b/packages/SystemUI/res/xml/media_session_expanded.xml @@ -28,57 +28,118 @@ app:layout_constraintBottom_toBottomOf="parent" /> <Constraint + android:id="@+id/header_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:layout_marginStart="@dimen/qs_media_padding" + android:layout_marginEnd="@dimen/qs_media_padding" + app:layout_constraintEnd_toStartOf="@id/actionPlayPause" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toBottomOf="@id/icon" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintHorizontal_bias="0" /> + <Constraint + android:id="@+id/header_artist" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/qs_media_padding" + android:layout_marginTop="0dp" + app:layout_constrainedWidth="true" + app:layout_constraintEnd_toStartOf="@id/actionPlayPause" + app:layout_constraintBottom_toTopOf="@id/media_action_barrier" + app:layout_constraintTop_toBottomOf="@id/header_title" + app:layout_constraintStart_toStartOf="@id/header_title" + app:layout_constraintVertical_bias="0" + app:layout_constraintHorizontal_bias="0" /> + + <Constraint android:id="@+id/actionPlayPause" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginEnd="@dimen/qs_media_padding" + android:layout_marginBottom="0dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" - app:layout_constraintBottom_toTopOf="@id/actionEnd" /> + app:layout_constraintBottom_toBottomOf="@id/header_artist" /> + <!-- + The bottom row of action buttons should remain in the same order when RTL, so their constraints + are set with right/left instead of start/end. + The chain is set to "spread" so that the progress bar can be weighted to fill any empty space. + --> <Constraint android:id="@+id/actionPrev" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_progress_bar" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toLeftOf="@id/media_progress_bar" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" + app:layout_constraintHorizontal_chainStyle="spread" /> <Constraint android:id="@+id/media_progress_bar" android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintStart_toEndOf="@id/actionPrev" - app:layout_constraintEnd_toStartOf="@id/actionNext" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/actionPrev" + app:layout_constraintRight_toLeftOf="@id/actionNext" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" + app:layout_constraintHorizontal_weight="1" /> <Constraint android:id="@+id/actionNext" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/media_progress_bar" - app:layout_constraintEnd_toStartOf="@id/actionStart" + app:layout_constraintLeft_toRightOf="@id/media_progress_bar" + app:layout_constraintRight_toLeftOf="@id/action0" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" /> <Constraint - android:id="@+id/actionStart" + android:id="@+id/action0" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/actionNext" - app:layout_constraintEnd_toStartOf="@id/actionEnd" + app:layout_constraintLeft_toRightOf="@id/actionNext" + app:layout_constraintRight_toLeftOf="@id/action1" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" /> <Constraint - android:id="@+id/actionEnd" + android:id="@+id/action1" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/actionStart" - app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintLeft_toRightOf="@id/action0" + app:layout_constraintRight_toLeftOf="@id/action2" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_artist" /> + + <Constraint + android:id="@+id/action2" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/action1" + app:layout_constraintRight_toLeftOf="@id/action3" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" /> -</ConstraintSet>
\ No newline at end of file + <Constraint + android:id="@+id/action3" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/action2" + app:layout_constraintRight_toLeftOf="@id/action4" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_artist" /> + + <Constraint + android:id="@+id/action4" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/action3" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_artist" /> +</ConstraintSet> diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java index ffd15460ce91..458d22efd206 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java @@ -96,7 +96,7 @@ public class EmergencyButton extends Button { **/ public void reloadColors() { int color = Utils.getColorAttrDefaultColor(getContext(), - android.R.attr.textColorPrimaryInverse); + com.android.internal.R.attr.textColorOnAccent); setTextColor(color); setBackground(getContext() .getDrawable(com.android.systemui.R.drawable.kg_emergency_button_background)); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java index 1efda7edee2f..77044ed33113 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java @@ -188,14 +188,13 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { enableClipping(false); setTranslationY(0); - AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 280 /* duration */, - mDisappearYTranslation, mDisappearAnimationUtils.getInterpolator(), - getAnimationListener(InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_DISAPPEAR)); DisappearAnimationUtils disappearAnimationUtils = needsSlowUnlockTransition ? mDisappearAnimationUtilsLocked : mDisappearAnimationUtils; - disappearAnimationUtils.startAnimation2d(mViews, - () -> { + disappearAnimationUtils.createAnimation( + this, 0, 200, mDisappearYTranslation, false, + mDisappearAnimationUtils.getInterpolator(), () -> { + getAnimationListener(InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_DISAPPEAR); enableClipping(true); if (finishRunnable != null) { finishRunnable.run(); diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java index e0d0fc25943b..7b98f2759d80 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java @@ -19,6 +19,8 @@ import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.VectorDrawable; import android.util.AttributeSet; import android.view.MotionEvent; @@ -37,8 +39,14 @@ public class NumPadButton extends AlphaOptimizedImageButton { public NumPadButton(Context context, AttributeSet attrs) { super(context, attrs); - mAnimator = new NumPadAnimator(context, getBackground().mutate(), - attrs.getStyleAttribute()); + Drawable background = getBackground(); + if (background instanceof GradientDrawable) { + mAnimator = new NumPadAnimator(context, background.mutate(), + attrs.getStyleAttribute()); + } else { + mAnimator = null; + } + } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java index 88a0bcec0542..5cab547ee435 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java @@ -18,6 +18,8 @@ package com.android.keyguard; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.PowerManager; import android.os.SystemClock; import android.util.AttributeSet; @@ -129,8 +131,13 @@ public class NumPadKey extends ViewGroup { setContentDescription(mDigitText.getText().toString()); - mAnimator = new NumPadAnimator(context, getBackground().mutate(), - R.style.NumPadKey, mDigitText); + Drawable background = getBackground(); + if (background instanceof GradientDrawable) { + mAnimator = new NumPadAnimator(context, background.mutate(), + R.style.NumPadKey, mDigitText); + } else { + mAnimator = null; + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 3a6165c03e24..031e3781ae9d 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -27,6 +27,7 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.os.Bundle; +import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; @@ -105,6 +106,10 @@ public class SystemUIApplication extends Application implements mBootCompleteCache = mSysUIComponent.provideBootCacheImpl(); log.traceEnd(); + // Enable Looper trace points. + // This allows us to see Handler callbacks on traces. + Looper.getMainLooper().setTraceTag(Trace.TRACE_TAG_APP); + // Set the application theme that is inherited by all services. Note that setting the // application theme in the manifest does only work for activities. Keep this in sync with // the theme set there. diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt new file mode 100644 index 000000000000..6615f6b0b9eb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt @@ -0,0 +1,132 @@ +package com.android.systemui.broadcast + +import android.annotation.AnyThread +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.util.wakelock.WakeLock +import java.util.concurrent.Executor +import javax.inject.Inject + +/** + * SystemUI master Broadcast sender + * + * This class dispatches broadcasts on background thread to avoid synchronous call to binder. Use + * this class instead of calling [Context.sendBroadcast] directly. + */ +@SysUISingleton +class BroadcastSender @Inject constructor( + private val context: Context, + private val wakeLockBuilder: WakeLock.Builder, + @Background private val bgExecutor: Executor +) { + + private val WAKE_LOCK_TAG = "SysUI:BroadcastSender" + private val WAKE_LOCK_SEND_REASON = "sendInBackground" + + /** + * Sends broadcast via [Context.sendBroadcast] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcast(intent: Intent) { + sendInBackground { + context.sendBroadcast(intent) + } + } + + /** + * Sends broadcast via [Context.sendBroadcast] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcast(intent: Intent, receiverPermission: String?) { + sendInBackground { + context.sendBroadcast(intent, receiverPermission) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser(intent: Intent, userHandle: UserHandle) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser(intent: Intent, userHandle: UserHandle, receiverPermission: String?) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle, receiverPermission) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser( + intent: Intent, + userHandle: UserHandle, + receiverPermission: String?, + options: Bundle? + ) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle, receiverPermission, options) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser( + intent: Intent, + userHandle: UserHandle, + receiverPermission: String?, + appOp: Int + ) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle, receiverPermission, appOp) + } + } + + /** + * Sends [Intent.ACTION_CLOSE_SYSTEM_DIALOGS] broadcast to the system. + */ + @AnyThread + fun closeSystemDialogs() { + sendInBackground { + context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + } + } + + /** + * Dispatches parameter on background executor while holding a wakelock. + */ + private fun sendInBackground(callable: () -> Unit) { + val broadcastWakelock = wakeLockBuilder.setTag(WAKE_LOCK_TAG) + .setMaxTimeout(5000) + .build() + broadcastWakelock.acquire(WAKE_LOCK_SEND_REASON) + bgExecutor.execute { + try { + callable.invoke() + } finally { + broadcastWakelock.release(WAKE_LOCK_SEND_REASON) + } + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index 40662536e57e..f9115b20ca06 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -17,10 +17,13 @@ package com.android.systemui.controls.management import android.content.ComponentName +import android.content.res.Configuration +import android.content.res.Resources import android.graphics.Rect import android.os.Bundle import android.service.controls.Control import android.service.controls.DeviceTypes +import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -32,7 +35,6 @@ import android.widget.TextView import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.ViewCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat -import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.android.systemui.R import com.android.systemui.controls.ControlInterface @@ -56,11 +58,32 @@ class ControlAdapter( const val TYPE_ZONE = 0 const val TYPE_CONTROL = 1 const val TYPE_DIVIDER = 2 - } - val spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { - override fun getSpanSize(position: Int): Int { - return if (getItemViewType(position) != TYPE_CONTROL) 2 else 1 + /** + * For low-dp width screens that also employ an increased font scale, adjust the + * number of columns. This helps prevent text truncation on these devices. + * + */ + @JvmStatic + fun findMaxColumns(res: Resources): Int { + var maxColumns = res.getInteger(R.integer.controls_max_columns) + val maxColumnsAdjustWidth = + res.getInteger(R.integer.controls_max_columns_adjust_below_width_dp) + + val outValue = TypedValue() + res.getValue(R.dimen.controls_max_columns_adjust_above_font_scale, outValue, true) + val maxColumnsAdjustFontScale = outValue.getFloat() + + val config = res.configuration + val isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT + if (isPortrait && + config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED && + config.screenWidthDp <= maxColumnsAdjustWidth && + config.fontScale >= maxColumnsAdjustFontScale) { + maxColumns-- + } + + return maxColumns } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt index 6f94943472b1..f611c3ef966d 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt @@ -195,10 +195,11 @@ class ControlsEditingActivity @Inject constructor( val margin = resources .getDimensionPixelSize(R.dimen.controls_card_margin) val itemDecorator = MarginItemDecorator(margin, margin) + val spanCount = ControlAdapter.findMaxColumns(resources) recyclerView.apply { this.adapter = adapter - layoutManager = object : GridLayoutManager(recyclerView.context, 2) { + layoutManager = object : GridLayoutManager(recyclerView.context, spanCount) { // This will remove from the announcement the row corresponding to the divider, // as it's not something that should be announced. @@ -210,7 +211,12 @@ class ControlsEditingActivity @Inject constructor( return if (initial > 0) initial - 1 else initial } }.apply { - spanSizeLookup = adapter.spanSizeLookup + spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return if (adapter?.getItemViewType(position) + != ControlAdapter.TYPE_CONTROL) spanCount else 1 + } + } } addItemDecoration(itemDecorator) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt index cb67454195ec..747bcbe1c229 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt @@ -60,11 +60,17 @@ class StructureAdapter( val margin = itemView.context.resources .getDimensionPixelSize(R.dimen.controls_card_margin) val itemDecorator = MarginItemDecorator(margin, margin) + val spanCount = ControlAdapter.findMaxColumns(itemView.resources) recyclerView.apply { this.adapter = controlAdapter - layoutManager = GridLayoutManager(recyclerView.context, 2).apply { - spanSizeLookup = controlAdapter.spanSizeLookup + layoutManager = GridLayoutManager(recyclerView.context, spanCount).apply { + spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return if (adapter?.getItemViewType(position) + != ControlAdapter.TYPE_CONTROL) spanCount else 1 + } + } } addItemDecoration(itemDecorator) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index 5c1d8c3929cb..e53f2673841c 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -16,11 +16,11 @@ package com.android.systemui.controls.ui +import android.annotation.AnyThread import android.annotation.MainThread import android.app.Dialog import android.app.PendingIntent import android.content.Context -import android.content.Intent import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.database.ContentObserver @@ -35,6 +35,7 @@ import android.service.controls.actions.FloatAction import android.util.Log import android.view.HapticFeedbackConstants import com.android.internal.annotations.VisibleForTesting +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main @@ -53,6 +54,7 @@ class ControlActionCoordinatorImpl @Inject constructor( private val bgExecutor: DelayableExecutor, @Main private val uiExecutor: DelayableExecutor, private val activityStarter: ActivityStarter, + private val broadcastSender: BroadcastSender, private val keyguardStateController: KeyguardStateController, private val taskViewFactory: Optional<TaskViewFactory>, private val controlsMetricsLogger: ControlsMetricsLogger, @@ -199,11 +201,12 @@ class ControlActionCoordinatorImpl @Inject constructor( false } + @AnyThread @VisibleForTesting fun bouncerOrRun(action: Action, authRequired: Boolean) { if (keyguardStateController.isShowing() && authRequired) { if (isLocked) { - context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + broadcastSender.closeSystemDialogs() // pending actions will only run after the control state has been refreshed pendingAction = action @@ -233,7 +236,10 @@ class ControlActionCoordinatorImpl @Inject constructor( // make sure the intent is valid before attempting to open the dialog if (activities.isNotEmpty() && taskViewFactory.isPresent) { taskViewFactory.get().create(context, uiExecutor, { - dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also { + dialog = DetailDialog( + activityContext, broadcastSender, + it, pendingIntent, cvh + ).also { it.setOnDismissListener { _ -> dialog = null } it.show() } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 59c291cf9e5c..1268250137b8 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -25,12 +25,10 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.SharedPreferences -import android.content.res.Configuration import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.service.controls.Control import android.util.Log -import android.util.TypedValue import android.view.ContextThemeWrapper import android.view.LayoutInflater import android.view.View @@ -51,6 +49,7 @@ import com.android.systemui.controls.CustomIconCache import com.android.systemui.controls.controller.ControlInfo import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.StructureInfo +import com.android.systemui.controls.management.ControlAdapter import com.android.systemui.controls.management.ControlsEditingActivity import com.android.systemui.controls.management.ControlsFavoritingActivity import com.android.systemui.controls.management.ControlsListingController @@ -386,7 +385,7 @@ class ControlsUiControllerImpl @Inject constructor ( visibility = View.VISIBLE } - val maxColumns = findMaxColumns() + val maxColumns = ControlAdapter.findMaxColumns(activityContext.resources) val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup var lastRow: ViewGroup = createRow(inflater, listView) @@ -432,32 +431,6 @@ class ControlsUiControllerImpl @Inject constructor ( } } - /** - * For low-dp width screens that also employ an increased font scale, adjust the - * number of columns. This helps prevent text truncation on these devices. - */ - private fun findMaxColumns(): Int { - val res = activityContext.resources - var maxColumns = res.getInteger(R.integer.controls_max_columns) - val maxColumnsAdjustWidth = - res.getInteger(R.integer.controls_max_columns_adjust_below_width_dp) - - val outValue = TypedValue() - res.getValue(R.dimen.controls_max_columns_adjust_above_font_scale, outValue, true) - val maxColumnsAdjustFontScale = outValue.getFloat() - - val config = res.configuration - val isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT - if (isPortrait && - config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED && - config.screenWidthDp <= maxColumnsAdjustWidth && - config.fontScale >= maxColumnsAdjustFontScale) { - maxColumns-- - } - - return maxColumns - } - override fun getPreferredStructure(structures: List<StructureInfo>): StructureInfo { if (structures.isEmpty()) return EMPTY_STRUCTURE diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt index dc3d1b52495c..80589a2711cc 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt @@ -33,6 +33,7 @@ import android.view.WindowManager import android.widget.ImageView import com.android.internal.policy.ScreenDecorationsUtils import com.android.systemui.R +import com.android.systemui.broadcast.BroadcastSender import com.android.wm.shell.TaskView /** @@ -42,6 +43,7 @@ import com.android.wm.shell.TaskView */ class DetailDialog( val activityContext: Context, + val broadcastSender: BroadcastSender, val taskView: TaskView, val pendingIntent: PendingIntent, val cvh: ControlViewHolder @@ -147,7 +149,7 @@ class DetailDialog( // startActivity() below is called. removeDetailTask() dismiss() - context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + broadcastSender.closeSystemDialogs() pendingIntent.send() } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java index 69f15e692065..995df19f64c2 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java @@ -23,8 +23,6 @@ import android.util.MathUtils; import android.view.View; import android.view.ViewGroup; -import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.complication.ComplicationHostViewController; import com.android.systemui.dreams.dagger.DreamOverlayComponent; @@ -39,9 +37,6 @@ import javax.inject.Named; */ @DreamOverlayComponent.DreamOverlayScope public class DreamOverlayContainerViewController extends ViewController<DreamOverlayContainerView> { - // The height of the area at the top of the dream overlay to allow dragging down the - // notifications shade. - private final int mDreamOverlayNotificationsDragAreaHeight; private final DreamOverlayStatusBarViewController mStatusBarViewController; private final ComplicationHostViewController mComplicationHostViewController; @@ -79,9 +74,6 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve super(containerView); mDreamOverlayContentView = contentView; mStatusBarViewController = statusBarViewController; - mDreamOverlayNotificationsDragAreaHeight = - mView.getResources().getDimensionPixelSize( - R.dimen.dream_overlay_notifications_drag_area_height); mComplicationHostViewController = complicationHostViewController; final View view = mComplicationHostViewController.getView(); @@ -117,11 +109,6 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve return mView; } - @VisibleForTesting - int getDreamOverlayNotificationsDragAreaHeight() { - return mDreamOverlayNotificationsDragAreaHeight; - } - private void updateBurnInOffsets() { int burnInOffset = mMaxBurnInOffset; diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index b590412dd48c..2db3de173257 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -16,6 +16,7 @@ package com.android.systemui.flags; +import com.android.internal.annotations.Keep; import com.android.systemui.R; import java.lang.reflect.Field; @@ -154,6 +155,7 @@ public class Flags { new BooleanFlag(1000, true); // 1100 - windowing + @Keep public static final SysPropBooleanFlag WM_ENABLE_SHELL_TRANSITIONS = new SysPropBooleanFlag(1100, "persist.wm.debug.shell_transit", false); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 831a606e95b2..510d15bd7b73 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -54,6 +54,7 @@ import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.GhostedViewLaunchAnimatorController; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.monet.ColorScheme; @@ -104,10 +105,18 @@ public class MediaControlPanel { R.id.action4 }; + // Buttons to show in small player when using semantic actions + private static final List<Integer> SEMANTIC_ACTION_IDS = List.of( + R.id.actionPlayPause, + R.id.actionPrev, + R.id.actionNext + ); + private final SeekBarViewModel mSeekBarViewModel; private SeekBarObserver mSeekBarObserver; protected final Executor mBackgroundExecutor; private final ActivityStarter mActivityStarter; + private final BroadcastSender mBroadcastSender; private Context mContext; private MediaViewHolder mMediaViewHolder; @@ -142,14 +151,16 @@ public class MediaControlPanel { */ @Inject public MediaControlPanel(Context context, @Background Executor backgroundExecutor, - ActivityStarter activityStarter, MediaViewController mediaViewController, - SeekBarViewModel seekBarViewModel, Lazy<MediaDataManager> lazyMediaDataManager, + ActivityStarter activityStarter, BroadcastSender broadcastSender, + MediaViewController mediaViewController, SeekBarViewModel seekBarViewModel, + Lazy<MediaDataManager> lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) { mContext = context; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; + mBroadcastSender = broadcastSender; mSeekBarViewModel = seekBarViewModel; mMediaViewController = mediaViewController; mMediaDataManagerLazy = lazyMediaDataManager; @@ -501,11 +512,11 @@ public class MediaControlPanel { MediaButton semanticActions = data.getSemanticActions(); actionIcons = new ArrayList<MediaAction>(); - actionIcons.add(semanticActions.getStartCustom()); + actionIcons.add(semanticActions.getCustom0()); actionIcons.add(semanticActions.getPrevOrCustom()); actionIcons.add(semanticActions.getPlayOrPause()); actionIcons.add(semanticActions.getNextOrCustom()); - actionIcons.add(semanticActions.getEndCustom()); + actionIcons.add(semanticActions.getCustom1()); actionsWhenCollapsed = new ArrayList<Integer>(); actionsWhenCollapsed.add(1); @@ -562,6 +573,9 @@ public class MediaControlPanel { /** Bind elements specific to PlayerSessionViewHolder */ private void bindSessionPlayer(@NonNull MediaData data, String key) { + ConstraintSet expandedSet = mMediaViewController.getExpandedLayout(); + ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); + // Default colors int surfaceColor = mBackgroundColor; int accentPrimary = com.android.settingslib.Utils.getColorAttr(mContext, @@ -575,25 +589,6 @@ public class MediaControlPanel { int textTertiary = com.android.settingslib.Utils.getColorAttr(mContext, com.android.internal.R.attr.textColorTertiary).getDefaultColor(); - // App icon - use launcher icon - ImageView appIconView = mMediaViewHolder.getAppIcon(); - appIconView.clearColorFilter(); - try { - Drawable icon = mContext.getPackageManager().getApplicationIcon( - data.getPackageName()); - appIconView.setImageDrawable(icon); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); - // Fall back to notification icon - if (data.getAppIcon() != null) { - appIconView.setImageIcon(data.getAppIcon()); - } else { - appIconView.setImageResource(R.drawable.ic_music_note); - } - int color = mContext.getColor(R.color.material_dynamic_secondary10); - appIconView.setColorFilter(color); - } - // Album art ColorScheme colorScheme = null; ImageView albumView = mMediaViewHolder.getAlbumView(); @@ -640,6 +635,25 @@ public class MediaControlPanel { ColorStateList.valueOf(surfaceColor)); mMediaViewHolder.getPlayer().setBackgroundTintList(bgColorList); + // App icon - use notification icon + ImageView appIconView = mMediaViewHolder.getAppIcon(); + appIconView.clearColorFilter(); + if (data.getAppIcon() != null && !data.getResumption()) { + appIconView.setImageIcon(data.getAppIcon()); + appIconView.setColorFilter(accentPrimary); + } else { + // Resume players use launcher icon + appIconView.setColorFilter(getGrayscaleFilter()); + try { + Drawable icon = mContext.getPackageManager().getApplicationIcon( + data.getPackageName()); + appIconView.setImageDrawable(icon); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); + appIconView.setImageResource(R.drawable.ic_music_note); + } + } + // Metadata text mMediaViewHolder.getTitleText().setTextColor(textPrimary); mMediaViewHolder.getArtistText().setTextColor(textSecondary); @@ -660,26 +674,68 @@ public class MediaControlPanel { // Media action buttons MediaButton semanticActions = data.getSemanticActions(); + PlayerSessionViewHolder sessionHolder = (PlayerSessionViewHolder) mMediaViewHolder; + ImageButton[] genericButtons = new ImageButton[]{ + sessionHolder.getAction0(), + sessionHolder.getAction1(), + sessionHolder.getAction2(), + sessionHolder.getAction3(), + sessionHolder.getAction4()}; + + ImageButton[] semanticButtons = new ImageButton[]{ + sessionHolder.getActionPlayPause(), + sessionHolder.getActionNext(), + sessionHolder.getActionPrev()}; + if (semanticActions != null) { - PlayerSessionViewHolder sessionHolder = (PlayerSessionViewHolder) mMediaViewHolder; + // Hide all the generic buttons + for (ImageButton b: genericButtons) { + setVisibleAndAlpha(collapsedSet, b.getId(), false); + setVisibleAndAlpha(expandedSet, b.getId(), false); + } // Play/pause button has a background sessionHolder.getActionPlayPause().setBackgroundTintList(accentColorList); setSemanticButton(sessionHolder.getActionPlayPause(), semanticActions.getPlayOrPause(), - ColorStateList.valueOf(textPrimaryInverse)); + ColorStateList.valueOf(textPrimaryInverse), collapsedSet, expandedSet, true); setSemanticButton(sessionHolder.getActionNext(), semanticActions.getNextOrCustom(), - textColorList); + textColorList, collapsedSet, expandedSet, true); setSemanticButton(sessionHolder.getActionPrev(), semanticActions.getPrevOrCustom(), - textColorList); - setSemanticButton(sessionHolder.getActionStart(), semanticActions.getStartCustom(), - textColorList); - setSemanticButton(sessionHolder.getActionEnd(), semanticActions.getEndCustom(), - textColorList); + textColorList, collapsedSet, expandedSet, true); + setSemanticButton(sessionHolder.getAction0(), semanticActions.getCustom0(), + textColorList, collapsedSet, expandedSet, false); + setSemanticButton(sessionHolder.getAction1(), semanticActions.getCustom1(), + textColorList, collapsedSet, expandedSet, false); } else { - Log.w(TAG, "Using semantic player, but did not get buttons"); + // Hide all the semantic buttons + for (int id : SEMANTIC_ACTION_IDS) { + setVisibleAndAlpha(collapsedSet, id, false); + setVisibleAndAlpha(expandedSet, id, false); + } + + // Set all the generic buttons + List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); + List<MediaAction> actions = data.getActions(); + int i = 0; + for (; i < actions.size(); i++) { + boolean showInCompact = actionsWhenCollapsed.contains(i); + setSemanticButton(genericButtons[i], actions.get(i), textColorList, collapsedSet, + expandedSet, showInCompact); + } + for (; i < 5; i++) { + // Hide any unused buttons + setSemanticButton(genericButtons[i], null, textColorList, collapsedSet, + expandedSet, false); + } } + // If disabled, set progress bar to INVISIBLE instead of GONE so layout weights still work + boolean seekbarEnabled = mSeekBarViewModel.getEnabled(); + expandedSet.setVisibility(R.id.media_progress_bar, + seekbarEnabled ? ConstraintSet.VISIBLE : ConstraintSet.INVISIBLE); + expandedSet.setAlpha(R.id.media_progress_bar, seekbarEnabled ? 1.0f : 0.0f); + // Long press buttons mMediaViewHolder.getLongPressText().setTextColor(textColorList); mMediaViewHolder.getSettingsText().setTextColor(textColorList); @@ -688,11 +744,11 @@ public class MediaControlPanel { mMediaViewHolder.getCancelText().setBackgroundTintList(accentColorList); mMediaViewHolder.getDismissText().setTextColor(textColorList); mMediaViewHolder.getDismissText().setBackgroundTintList(accentColorList); - } private void setSemanticButton(final ImageButton button, MediaAction mediaAction, - ColorStateList fgColor) { + ColorStateList fgColor, ConstraintSet collapsedSet, ConstraintSet expandedSet, + boolean showInCompact) { button.setImageTintList(fgColor); if (mediaAction != null) { button.setImageIcon(mediaAction.getIcon()); @@ -716,6 +772,9 @@ public class MediaControlPanel { button.setContentDescription(null); button.setEnabled(false); } + + setVisibleAndAlpha(collapsedSet, button.getId(), mediaAction != null && showInCompact); + setVisibleAndAlpha(expandedSet, button.getId(), mediaAction != null); } @Nullable @@ -899,7 +958,7 @@ public class MediaControlPanel { // Dismiss the card Smartspace data through Smartspace trampoline activity. mContext.startActivity(dismissIntent); } else { - mContext.sendBroadcast(dismissIntent); + mBroadcastSender.sendBroadcast(dismissIntent); } }); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index 500e82efdb0a..4cf6291fe35b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -149,11 +149,11 @@ data class MediaButton( /** * First custom action space */ - var startCustom: MediaAction? = null, + var custom0: MediaAction? = null, /** - * Last custom action space + * Second custom action space */ - var endCustom: MediaAction? = null + var custom1: MediaAction? = null ) /** State of a media action. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index ae5c1f2b19a9..de44a9c46963 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -21,6 +21,7 @@ import android.os.SystemProperties import android.util.Log import com.android.internal.annotations.VisibleForTesting import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.statusbar.NotificationLockscreenUserManager @@ -56,6 +57,7 @@ internal val SMARTSPACE_MAX_AGE = SystemProperties class MediaDataFilter @Inject constructor( private val context: Context, private val broadcastDispatcher: BroadcastDispatcher, + private val broadcastSender: BroadcastSender, private val lockscreenUserManager: NotificationLockscreenUserManager, @Main private val executor: Executor, private val systemClock: SystemClock @@ -249,7 +251,7 @@ class MediaDataFilter @Inject constructor( // Dismiss the card Smartspace data through Smartspace trampoline activity. context.startActivity(dismissIntent) } else { - context.sendBroadcast(dismissIntent) + broadcastSender.sendBroadcast(dismissIntent) } smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index fab06c288ce1..9e14fe91f21d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -752,8 +752,8 @@ class MediaDataManager( null } - actions.startCustom = customActions[customIdx++] - actions.endCustom = customActions[customIdx++] + actions.custom0 = customActions[customIdx++] + actions.custom1 = customActions[customIdx++] } return actions } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java index 77873e829be3..38604091c409 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java @@ -54,7 +54,7 @@ public class MediaProjectionPermissionActivity extends Activity private int mUid; private IMediaProjectionManager mService; - private SystemUIDialog mDialog; + private AlertDialog mDialog; @Override public void onCreate(Bundle icicle) { @@ -141,13 +141,18 @@ public class MediaProjectionPermissionActivity extends Activity dialogTitle = getString(R.string.media_projection_dialog_title, appName); } - mDialog = new SystemUIDialog(this); - mDialog.setTitle(dialogTitle); - mDialog.setIcon(R.drawable.ic_media_projection_permission); - mDialog.setMessage(dialogText); - mDialog.setPositiveButton(R.string.media_projection_action_text, this); - mDialog.setNeutralButton(android.R.string.cancel, this); - mDialog.setOnCancelListener(this); + mDialog = new AlertDialog.Builder(this, R.style.Theme_SystemUI_Dialog) + .setTitle(dialogTitle) + .setIcon(R.drawable.ic_media_projection_permission) + .setMessage(dialogText) + .setPositiveButton(R.string.media_projection_action_text, this) + .setNeutralButton(android.R.string.cancel, this) + .setOnCancelListener(this) + .create(); + + SystemUIDialog.registerDismissListener(mDialog); + SystemUIDialog.applyFlags(mDialog); + SystemUIDialog.setDialogSize(mDialog); mDialog.create(); mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true); @@ -186,7 +191,7 @@ public class MediaProjectionPermissionActivity extends Activity private Intent getMediaProjectionIntent(int uid, String packageName) throws RemoteException { IMediaProjection projection = mService.createProjection(uid, packageName, - MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */); + MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */); Intent intent = new Intent(); intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION, projection.asBinder()); return intent; diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt index e57b247da055..5f606969153c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt @@ -60,12 +60,24 @@ abstract class MediaViewHolder constructor(itemView: View) { val settings = itemView.requireViewById<View>(R.id.settings) val settingsText = itemView.requireViewById<TextView>(R.id.settings_text) + // Action Buttons + val action0 = itemView.requireViewById<ImageButton>(R.id.action0) + val action1 = itemView.requireViewById<ImageButton>(R.id.action1) + val action2 = itemView.requireViewById<ImageButton>(R.id.action2) + val action3 = itemView.requireViewById<ImageButton>(R.id.action3) + val action4 = itemView.requireViewById<ImageButton>(R.id.action4) + init { (player.background as IlluminationDrawable).let { it.registerLightSource(seamless) it.registerLightSource(cancel) it.registerLightSource(dismiss) it.registerLightSource(settings) + it.registerLightSource(action0) + it.registerLightSource(action1) + it.registerLightSource(action2) + it.registerLightSource(action3) + it.registerLightSource(action4) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt index 87d2cffea257..6928ebb8bb32 100644 --- a/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt @@ -31,16 +31,12 @@ class PlayerSessionViewHolder private constructor(itemView: View) : MediaViewHol val actionPlayPause = itemView.requireViewById<ImageButton>(R.id.actionPlayPause) val actionNext = itemView.requireViewById<ImageButton>(R.id.actionNext) val actionPrev = itemView.requireViewById<ImageButton>(R.id.actionPrev) - val actionStart = itemView.requireViewById<ImageButton>(R.id.actionStart) - val actionEnd = itemView.requireViewById<ImageButton>(R.id.actionEnd) init { (player.background as IlluminationDrawable).let { it.registerLightSource(actionPlayPause) it.registerLightSource(actionNext) it.registerLightSource(actionPrev) - it.registerLightSource(actionStart) - it.registerLightSource(actionEnd) } } @@ -49,8 +45,11 @@ class PlayerSessionViewHolder private constructor(itemView: View) : MediaViewHol R.id.actionPlayPause -> actionPlayPause R.id.actionNext -> actionNext R.id.actionPrev -> actionPrev - R.id.actionStart -> actionStart - R.id.actionEnd -> actionEnd + R.id.action0 -> action0 + R.id.action1 -> action1 + R.id.action2 -> action2 + R.id.action3 -> action3 + R.id.action4 -> action4 else -> { throw IllegalArgumentException() } @@ -90,8 +89,11 @@ class PlayerSessionViewHolder private constructor(itemView: View) : MediaViewHol R.id.actionPlayPause, R.id.actionNext, R.id.actionPrev, - R.id.actionStart, - R.id.actionEnd, + R.id.action0, + R.id.action1, + R.id.action2, + R.id.action3, + R.id.action4, R.id.icon ) val gutsIds = setOf( diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt index 20b2d4a452f5..dd3fa89dea66 100644 --- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt @@ -33,23 +33,6 @@ class PlayerViewHolder private constructor(itemView: View) : MediaViewHolder(ite override val elapsedTimeView = itemView.requireViewById<TextView>(R.id.media_elapsed_time) override val totalTimeView = itemView.requireViewById<TextView>(R.id.media_total_time) - // Action Buttons - val action0 = itemView.requireViewById<ImageButton>(R.id.action0) - val action1 = itemView.requireViewById<ImageButton>(R.id.action1) - val action2 = itemView.requireViewById<ImageButton>(R.id.action2) - val action3 = itemView.requireViewById<ImageButton>(R.id.action3) - val action4 = itemView.requireViewById<ImageButton>(R.id.action4) - - init { - (player.background as IlluminationDrawable).let { - it.registerLightSource(action0) - it.registerLightSource(action1) - it.registerLightSource(action2) - it.registerLightSource(action3) - it.registerLightSource(action4) - } - } - override fun getAction(id: Int): ImageButton { return when (id) { R.id.action0 -> action0 diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt index 329dec24a5c3..49cd16175f0a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt @@ -132,6 +132,8 @@ class SeekBarViewModel @Inject constructor( lateinit var logSmartspaceClick: () -> Unit + fun getEnabled() = _data.enabled + /** * Event indicating that the user has started interacting with the seek bar. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index 355c69f9a48d..a8141c0e2fec 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -21,7 +21,6 @@ import static android.view.WindowInsets.Type.statusBars; import android.app.WallpaperColors; import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -55,6 +54,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.statusbar.phone.SystemUIDialog; /** @@ -71,6 +71,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements final Context mContext; final MediaOutputController mMediaOutputController; + final BroadcastSender mBroadcastSender; @VisibleForTesting View mDialogView; @@ -98,11 +99,13 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } }; - public MediaOutputBaseDialog(Context context, MediaOutputController mediaOutputController) { + public MediaOutputBaseDialog(Context context, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController) { super(context, R.style.Theme_SystemUI_Dialog_Media); // Save the context that is wrapped with our theme. mContext = getContext(); + mBroadcastSender = broadcastSender; mMediaOutputController = mediaOutputController; mLayoutManager = new LinearLayoutManager(mContext); mListMaxHeight = context.getResources().getDimensionPixelSize( @@ -152,7 +155,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements dismiss(); }); mAppButton.setOnClickListener(v -> { - mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + mBroadcastSender.closeSystemDialogs(); if (mMediaOutputController.getAppLaunchIntent() != null) { mContext.startActivity(mMediaOutputController.getAppLaunchIntent()); } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 0c202e09b62e..0b6c68d17a4c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -53,7 +53,6 @@ import androidx.core.graphics.drawable.IconCompat; import androidx.mediarouter.media.MediaRouter; import androidx.mediarouter.media.MediaRouterParams; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; @@ -70,7 +69,6 @@ import com.android.systemui.monet.ColorScheme; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; -import com.android.systemui.statusbar.phone.ShadeController; import java.util.ArrayList; import java.util.Collection; @@ -95,12 +93,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private final String mPackageName; private final Context mContext; private final MediaSessionManager mMediaSessionManager; - private final LocalBluetoothManager mLocalBluetoothManager; - private final ShadeController mShadeController; private final ActivityStarter mActivityStarter; private final DialogLaunchAnimator mDialogLaunchAnimator; private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>(); - private final boolean mAboveStatusbar; private final CommonNotifCollection mNotifCollection; @VisibleForTesting final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); @@ -114,7 +109,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, LocalMediaManager mLocalMediaManager; private MediaOutputMetricLogger mMetricLogger; - private UiEventLogger mUiEventLogger; private int mColorActiveItem; private int mColorInactiveItem; @@ -124,23 +118,19 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @Inject public MediaOutputController(@NonNull Context context, String packageName, - boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager - lbm, ShadeController shadeController, ActivityStarter starter, - CommonNotifCollection notifCollection, UiEventLogger uiEventLogger, + MediaSessionManager mediaSessionManager, LocalBluetoothManager + lbm, ActivityStarter starter, + CommonNotifCollection notifCollection, DialogLaunchAnimator dialogLaunchAnimator, Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; - mLocalBluetoothManager = lbm; - mShadeController = shadeController; mActivityStarter = starter; - mAboveStatusbar = aboveStatusbar; mNotifCollection = notifCollection; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); - mUiEventLogger = uiEventLogger; mDialogLaunchAnimator = dialogLaunchAnimator; mNearbyMediaDevicesManager = nearbyMediaDevicesManagerOptional.orElse(null); mColorActiveItem = Utils.getColorStateListDefaultColor(mContext, @@ -630,18 +620,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mActivityStarter.startActivity(launchIntent, true, controller); } - void launchMediaOutputGroupDialog(View mediaOutputDialog) { - // We show the output group dialog from the output dialog. - MediaOutputController controller = new MediaOutputController(mContext, mPackageName, - mAboveStatusbar, mMediaSessionManager, mLocalBluetoothManager, mShadeController, - mActivityStarter, mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager)); - - MediaOutputGroupDialog dialog = new MediaOutputGroupDialog(mContext, mAboveStatusbar, - controller); - mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog); - } - boolean isActiveRemoteDevice(@NonNull MediaDevice device) { final List<String> features = device.getFeatures(); return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK) diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index 7696a1f63c01..7834ec0fa17f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -28,6 +28,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; /** @@ -37,9 +38,9 @@ import com.android.systemui.dagger.SysUISingleton; public class MediaOutputDialog extends MediaOutputBaseDialog { final UiEventLogger mUiEventLogger; - MediaOutputDialog(Context context, boolean aboveStatusbar, MediaOutputController - mediaOutputController, UiEventLogger uiEventLogger) { - super(context, mediaOutputController); + MediaOutputDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController, UiEventLogger uiEventLogger) { + super(context, broadcastSender, mediaOutputController); mUiEventLogger = uiEventLogger; mAdapter = new MediaOutputAdapter(mMediaOutputController, this); if (!aboveStatusbar) { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index a7e54801bf47..0d7d60ac5923 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -22,10 +22,10 @@ import android.view.View import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.media.nearby.NearbyMediaDevicesManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection -import com.android.systemui.statusbar.phone.ShadeController import java.util.Optional import javax.inject.Inject @@ -36,8 +36,8 @@ class MediaOutputDialogFactory @Inject constructor( private val context: Context, private val mediaSessionManager: MediaSessionManager, private val lbm: LocalBluetoothManager?, - private val shadeController: ShadeController, private val starter: ActivityStarter, + private val broadcastSender: BroadcastSender, private val notifCollection: CommonNotifCollection, private val uiEventLogger: UiEventLogger, private val dialogLaunchAnimator: DialogLaunchAnimator, @@ -52,10 +52,11 @@ class MediaOutputDialogFactory @Inject constructor( // Dismiss the previous dialog, if any. mediaOutputDialog?.dismiss() - val controller = MediaOutputController(context, packageName, aboveStatusBar, - mediaSessionManager, lbm, shadeController, starter, notifCollection, - uiEventLogger, dialogLaunchAnimator, nearbyMediaDevicesManagerOptional) - val dialog = MediaOutputDialog(context, aboveStatusBar, controller, uiEventLogger) + val controller = MediaOutputController(context, packageName, + mediaSessionManager, lbm, starter, notifCollection, + dialogLaunchAnimator, nearbyMediaDevicesManagerOptional) + val dialog = + MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger) mediaOutputDialog = dialog // Show the dialog. diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java index f1c66016a49a..bb3f969c86df 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java @@ -25,6 +25,7 @@ import android.view.WindowManager; import androidx.core.graphics.drawable.IconCompat; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; /** * Dialog for media output group. @@ -32,9 +33,9 @@ import com.android.systemui.R; // TODO(b/203073091): Remove this class once group logic been implemented. public class MediaOutputGroupDialog extends MediaOutputBaseDialog { - MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController - mediaOutputController) { - super(context, mediaOutputController); + MediaOutputGroupDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController) { + super(context, broadcastSender, mediaOutputController); mMediaOutputController.resetGroupMediaDevices(); mAdapter = new MediaOutputGroupAdapter(mMediaOutputController); if (!aboveStatusbar) { diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index b4e20fd7f32b..2ac34b22be5b 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -60,6 +60,7 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.settingslib.utils.PowerUtil; import com.android.systemui.R; import com.android.systemui.SystemUIApplication; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -160,17 +161,20 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { @VisibleForTesting SystemUIDialog mUsbHighTempDialog; private BatteryStateSnapshot mCurrentBatterySnapshot; private ActivityStarter mActivityStarter; + private final BroadcastSender mBroadcastSender; /** */ @Inject - public PowerNotificationWarnings(Context context, ActivityStarter activityStarter) { + public PowerNotificationWarnings(Context context, ActivityStarter activityStarter, + BroadcastSender broadcastSender) { mContext = context; mNoMan = mContext.getSystemService(NotificationManager.class); mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mKeyguard = mContext.getSystemService(KeyguardManager.class); mReceiver.init(); mActivityStarter = activityStarter; + mBroadcastSender = broadcastSender; mUseSevereDialog = mContext.getResources().getBoolean(R.bool.config_severe_battery_dialog); } @@ -258,7 +262,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { protected void showWarningNotification() { if (showSevereLowBatteryDialog()) { - mContext.sendBroadcast(new Intent(ACTION_ENABLE_SEVERE_BATTERY_DIALOG) + mBroadcastSender.sendBroadcast(new Intent(ACTION_ENABLE_SEVERE_BATTERY_DIALOG) .setPackage(mContext.getPackageName()) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND)); @@ -716,9 +720,9 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { mSaverConfirmation.dismiss(); } // Also close the notification shade, if it's open. - mContext.sendBroadcast( + mBroadcastSender.sendBroadcast( new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) - .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)); + .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)); final Uri uri = Uri.parse(getURL()); Context context = widget.getContext(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java index e1d20706c625..8bad2de189c5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java @@ -47,9 +47,6 @@ import java.util.concurrent.atomic.AtomicReference; public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.InternetViewHolder> { private static final String TAG = "InternetAdapter"; - private static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG"; - private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; - private static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller"; private final InternetDialogController mInternetDialogController; @Nullable @@ -169,11 +166,10 @@ public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.Intern } mWifiListLayout.setOnClickListener(v -> { if (wifiEntry.shouldEditBeforeConnect()) { - final Intent intent = new Intent(ACTION_WIFI_DIALOG); + final Intent intent = WifiUtils.getWifiDialogIntent(wifiEntry.getKey(), + true /* connectForCaller */); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, wifiEntry.getKey()); - intent.putExtra(EXTRA_CONNECT_FOR_CALLER, false); mContext.startActivity(intent); } mInternetDialogController.connect(wifiEntry); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index b3bc3be852fb..b322cbf6c60e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -112,7 +112,6 @@ public class InternetDialogController implements AccessPointController.AccessPoi "android.settings.NETWORK_PROVIDER_SETTINGS"; private static final String ACTION_WIFI_SCANNING_SETTINGS = "android.settings.WIFI_SCANNING_SETTINGS"; - private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT); public static final int NO_CELL_DATA_TYPE_ICON = 0; private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off; @@ -853,8 +852,8 @@ public class InternetDialogController implements AccessPointController.AccessPoi } if (status == WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) { - final Intent intent = new Intent("com.android.settings.WIFI_DIALOG") - .putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, mWifiEntry.getKey()); + final Intent intent = WifiUtils.getWifiDialogIntent(mWifiEntry.getKey(), + true /* connectForCaller */); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mActivityStarter.startActivity(intent, false /* dismissShade */); } else if (status == CONNECT_STATUS_FAILURE_UNKNOWN) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 50765f227554..009d4b9b48e6 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -88,10 +88,12 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.policy.PhoneWindow; import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.clipboardoverlay.ClipboardOverlayController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition; import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback; +import com.android.systemui.util.Assert; import com.google.common.util.concurrent.ListenableFuture; @@ -247,6 +249,7 @@ public class ScreenshotController { private final ImageExporter mImageExporter; private final Executor mMainExecutor; private final ExecutorService mBgExecutor; + private final BroadcastSender mBroadcastSender; private final WindowManager mWindowManager; private final WindowManager.LayoutParams mWindowLayoutParams; @@ -271,7 +274,6 @@ public class ScreenshotController { private String mPackageName = ""; private BroadcastReceiver mCopyBroadcastReceiver; - /** Tracks config changes that require re-creating UI */ private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges( ActivityInfo.CONFIG_ORIENTATION @@ -293,7 +295,8 @@ public class ScreenshotController { ScrollCaptureController scrollCaptureController, LongScreenshotData longScreenshotHolder, ActivityManager activityManager, - TimeoutHandler timeoutHandler) { + TimeoutHandler timeoutHandler, + BroadcastSender broadcastSender) { mScreenshotSmartActions = screenshotSmartActions; mNotificationsController = screenshotNotificationsController; mScrollCaptureClient = scrollCaptureClient; @@ -304,6 +307,7 @@ public class ScreenshotController { mLongScreenshotHolder = longScreenshotHolder; mIsLowRamDevice = activityManager.isLowRamDevice(); mBgExecutor = Executors.newSingleThreadExecutor(); + mBroadcastSender = broadcastSender; mScreenshotHandler = timeoutHandler; mScreenshotHandler.setDefaultTimeoutMillis(SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS); @@ -355,8 +359,10 @@ public class ScreenshotController { ClipboardOverlayController.SELF_PERMISSION, null, Context.RECEIVER_NOT_EXPORTED); } + @MainThread void takeScreenshotFullscreen(ComponentName topComponent, Consumer<Uri> finisher, RequestCallback requestCallback) { + Assert.isMainThread(); mCurrentRequestCallback = requestCallback; DisplayMetrics displayMetrics = new DisplayMetrics(); getDefaultDisplay().getRealMetrics(displayMetrics); @@ -365,11 +371,12 @@ public class ScreenshotController { new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels)); } + @MainThread void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds, Insets visibleInsets, int taskId, int userId, ComponentName topComponent, Consumer<Uri> finisher, RequestCallback requestCallback) { // TODO: use task Id, userId, topComponent for smart handler - + Assert.isMainThread(); if (screenshot == null) { Log.e(TAG, "Got null bitmap from screenshot message"); mNotificationsController.notifyScreenshotError( @@ -392,8 +399,10 @@ public class ScreenshotController { /** * Displays a screenshot selector */ + @MainThread void takeScreenshotPartial(ComponentName topComponent, final Consumer<Uri> finisher, RequestCallback requestCallback) { + Assert.isMainThread(); mScreenshotView.reset(); mCurrentRequestCallback = requestCallback; @@ -517,7 +526,7 @@ public class ScreenshotController { saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, topComponent, true); - mContext.sendBroadcast(new Intent(ClipboardOverlayController.SCREENSHOT_ACTION), + mBroadcastSender.sendBroadcast(new Intent(ClipboardOverlayController.SCREENSHOT_ACTION), ClipboardOverlayController.SELF_PERMISSION); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index 267ee6d2d177..a0388de5150c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -259,6 +259,7 @@ class NotificationShadeDepthController @Inject constructor( addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { keyguardAnimator = null + wakeAndUnlockBlurRadius = 0f scheduleUpdate() } }) @@ -439,7 +440,7 @@ class NotificationShadeDepthController @Inject constructor( it.println("StatusBarWindowBlurController:") it.increaseIndent() it.println("shadeExpansion: $shadeExpansion") - it.println("shouldApplyShaeBlur: ${shouldApplyShadeBlur()}") + it.println("shouldApplyShadeBlur: ${shouldApplyShadeBlur()}") it.println("shadeAnimation: ${shadeAnimation.radius}") it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}") it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index 369ef343a4e2..2baa0797b41f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -230,7 +230,13 @@ public class ShadeListBuilder implements Dumpable { mPipelineState.requireState(STATE_IDLE); mNotifSections.clear(); + NotifSectioner lastSection = null; for (NotifSectioner sectioner : sectioners) { + if (lastSection != null && lastSection.getBucket() > sectioner.getBucket()) { + throw new IllegalArgumentException("setSectioners with non contiguous sections " + + lastSection.getName() + " - " + lastSection.getBucket() + " & " + + sectioner.getName() + " - " + sectioner.getBucket()); + } final NotifSection section = new NotifSection(sectioner, mNotifSections.size()); final NotifComparator sectionComparator = section.getComparator(); mNotifSections.add(section); @@ -238,6 +244,7 @@ public class ShadeListBuilder implements Dumpable { if (sectionComparator != null) { sectionComparator.setInvalidationListener(this::onNotifComparatorInvalidated); } + lastSection = sectioner; } mNotifSections.add(new NotifSection(DEFAULT_SECTIONER, mNotifSections.size())); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java index 22300d8c180d..1237c70fcbe3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java @@ -16,36 +16,16 @@ package com.android.systemui.statusbar.notification.collection.coordinator; -import static android.app.Notification.VISIBILITY_SECRET; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.UserHandle; -import android.provider.Settings; -import android.service.notification.StatusBarNotification; - -import androidx.annotation.MainThread; - import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider; -import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; -import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import javax.inject.Inject; @@ -56,171 +36,48 @@ import javax.inject.Inject; @CoordinatorScope public class KeyguardCoordinator implements Coordinator { private static final String TAG = "KeyguardCoordinator"; - - private final Context mContext; - private final Handler mMainHandler; - private final KeyguardStateController mKeyguardStateController; - private final NotificationLockscreenUserManager mLockscreenUserManager; - private final BroadcastDispatcher mBroadcastDispatcher; private final StatusBarStateController mStatusBarStateController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final HighPriorityProvider mHighPriorityProvider; private final SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider; - - private boolean mHideSilentNotificationsOnLockscreen; + private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; @Inject public KeyguardCoordinator( - Context context, - @MainThread Handler mainThreadHandler, - KeyguardStateController keyguardStateController, - NotificationLockscreenUserManager lockscreenUserManager, - BroadcastDispatcher broadcastDispatcher, StatusBarStateController statusBarStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, HighPriorityProvider highPriorityProvider, - SectionHeaderVisibilityProvider sectionHeaderVisibilityProvider) { - mContext = context; - mMainHandler = mainThreadHandler; - mKeyguardStateController = keyguardStateController; - mLockscreenUserManager = lockscreenUserManager; - mBroadcastDispatcher = broadcastDispatcher; + SectionHeaderVisibilityProvider sectionHeaderVisibilityProvider, + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { mStatusBarStateController = statusBarStateController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mHighPriorityProvider = highPriorityProvider; mSectionHeaderVisibilityProvider = sectionHeaderVisibilityProvider; + mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider; } @Override public void attach(NotifPipeline pipeline) { - readShowSilentNotificationSetting(); setupInvalidateNotifListCallbacks(); // Filter at the "finalize" stage so that views remain bound by PreparationCoordinator pipeline.addFinalizeFilter(mNotifFilter); - + mKeyguardNotificationVisibilityProvider + .addOnStateChangedListener(this::invalidateListFromFilter); updateSectionHeadersVisibility(); } private final NotifFilter mNotifFilter = new NotifFilter(TAG) { @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { - final StatusBarNotification sbn = entry.getSbn(); - - // FILTER OUT the notification when the keyguard is showing and... - if (mKeyguardStateController.isShowing()) { - // ... user settings or the device policy manager doesn't allow lockscreen - // notifications; - if (!mLockscreenUserManager.shouldShowLockscreenNotifications()) { - return true; - } - - final int currUserId = mLockscreenUserManager.getCurrentUserId(); - final int notifUserId = (sbn.getUser().getIdentifier() == UserHandle.USER_ALL) - ? currUserId : sbn.getUser().getIdentifier(); - - // ... user is in lockdown - if (mKeyguardUpdateMonitor.isUserInLockdown(currUserId) - || mKeyguardUpdateMonitor.isUserInLockdown(notifUserId)) { - return true; - } - - // ... device is in public mode and the user's settings doesn't allow - // notifications to show in public mode - if (mLockscreenUserManager.isLockscreenPublicMode(currUserId) - || mLockscreenUserManager.isLockscreenPublicMode(notifUserId)) { - if (entry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET) { - return true; - } - - if (!mLockscreenUserManager.userAllowsNotificationsInPublic(currUserId) - || !mLockscreenUserManager.userAllowsNotificationsInPublic( - notifUserId)) { - return true; - } - } - - // ... neither this notification nor its group have high enough priority - // to be shown on the lockscreen - if (entry.getParent() != null) { - final GroupEntry parent = entry.getParent(); - if (priorityExceedsLockscreenShowingThreshold(parent)) { - return false; - } - } - return !priorityExceedsLockscreenShowingThreshold(entry); - } - return false; + return mKeyguardNotificationVisibilityProvider.hideNotification(entry); } }; - private boolean priorityExceedsLockscreenShowingThreshold(ListEntry entry) { - if (entry == null) { - return false; - } - if (mHideSilentNotificationsOnLockscreen) { - return mHighPriorityProvider.isHighPriority(entry); - } else { - return entry.getRepresentativeEntry() != null - && !entry.getRepresentativeEntry().getRanking().isAmbient(); - } - } - // TODO(b/206118999): merge this class with SensitiveContentCoordinator which also depends on // these same updates private void setupInvalidateNotifListCallbacks() { - // register onKeyguardShowing callback - mKeyguardStateController.addCallback(mKeyguardCallback); - mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); - - // register lockscreen settings changed callbacks: - final ContentObserver settingsObserver = new ContentObserver(mMainHandler) { - @Override - public void onChange(boolean selfChange, Uri uri) { - if (uri.equals(Settings.Secure.getUriFor( - Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS))) { - readShowSilentNotificationSetting(); - } - - if (mKeyguardStateController.isShowing()) { - invalidateListFromFilter("Settings " + uri + " changed"); - } - } - }; - - mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), - false, - settingsObserver, - UserHandle.USER_ALL); - mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), - true, - settingsObserver, - UserHandle.USER_ALL); - - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(Settings.Global.ZEN_MODE), - false, - settingsObserver); - - mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS), - false, - settingsObserver, - UserHandle.USER_ALL); - - // register (maybe) public mode changed callbacks: - mStatusBarStateController.addCallback(mStatusBarStateListener); - mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mKeyguardStateController.isShowing()) { - // maybe public mode changed - invalidateListFromFilter(intent.getAction()); - } - }}, new IntentFilter(Intent.ACTION_USER_SWITCHED)); } private void invalidateListFromFilter(String reason) { @@ -228,49 +85,10 @@ public class KeyguardCoordinator implements Coordinator { mNotifFilter.invalidateList(); } - private void readShowSilentNotificationSetting() { - mHideSilentNotificationsOnLockscreen = - Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, - 1) == 0; - } - private void updateSectionHeadersVisibility() { boolean onKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD; boolean neverShowSections = mSectionHeaderVisibilityProvider.getNeverShowSectionHeaders(); boolean showSections = !onKeyguard && !neverShowSections; mSectionHeaderVisibilityProvider.setSectionHeadersVisible(showSections); } - - private final KeyguardStateController.Callback mKeyguardCallback = - new KeyguardStateController.Callback() { - @Override - public void onUnlockedChanged() { - invalidateListFromFilter("onUnlockedChanged"); - } - - @Override - public void onKeyguardShowingChanged() { - invalidateListFromFilter("onKeyguardShowingChanged"); - } - }; - - private final StatusBarStateController.StateListener mStatusBarStateListener = - new StatusBarStateController.StateListener() { - @Override - public void onStateChanged(int newState) { - // maybe public mode changed - invalidateListFromFilter("onStatusBarStateChanged"); - } - }; - - private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback = - new KeyguardUpdateMonitorCallback() { - @Override - public void onStrongAuthStateChanged(int userId) { - // maybe lockdown mode changed - invalidateListFromFilter("onStrongAuthStateChanged"); - } - }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt index c35b77cfb4e0..6db544c77f87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt @@ -57,6 +57,7 @@ class NodeSpecBuilder( var currentSection: NotifSection? = null val prevSections = mutableSetOf<NotifSection?>() + var lastSection: NotifSection? = null val showHeaders = sectionHeaderVisibilityProvider.sectionHeadersVisible val sectionOrder = mutableListOf<NotifSection?>() val sectionHeaders = mutableMapOf<NotifSection?, NodeController?>() @@ -65,6 +66,14 @@ class NodeSpecBuilder( for (entry in notifList) { val section = entry.section!! + lastSection?.let { + if (it.bucket > section.bucket) { + throw IllegalStateException("buildNodeSpec with non contiguous section " + + "buckets ${it.sectioner.name} - ${it.bucket} & " + + "${it.sectioner.name} - ${it.bucket}") + } + } + lastSection = section if (prevSections.contains(section)) { throw java.lang.RuntimeException("Section ${section.label} has been duplicated") } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt new file mode 100644 index 000000000000..70c9a16b9d7a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt @@ -0,0 +1,186 @@ +package com.android.systemui.statusbar.notification.interruption + +import android.app.Notification +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.database.ContentObserver +import android.net.Uri +import android.os.Handler +import android.os.UserHandle +import android.provider.Settings +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.keyguard.KeyguardUpdateMonitorCallback +import com.android.systemui.CoreStartable +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.ListenerSet +import java.util.function.Consumer +import javax.inject.Inject + +/** + * Determines if notifications should be visible based on the state of the keyguard + */ +class KeyguardNotificationVisibilityProvider @Inject constructor( + context: Context, + @Main private val handler: Handler, + private val keyguardStateController: KeyguardStateController, + private val lockscreenUserManager: NotificationLockscreenUserManager, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val highPriorityProvider: HighPriorityProvider, + private val statusBarStateController: StatusBarStateController, + private val broadcastDispatcher: BroadcastDispatcher +) : CoreStartable(context) { + private val onStateChangedListeners = ListenerSet<Consumer<String>>() + private var hideSilentNotificationsOnLockscreen: Boolean = false + + override fun start() { + readShowSilentNotificationSetting() + keyguardStateController.addCallback(object : KeyguardStateController.Callback { + override fun onUnlockedChanged() { + notifyStateChanged("onUnlockedChanged") + } + + override fun onKeyguardShowingChanged() { + notifyStateChanged("onKeyguardShowingChanged") + } + }) + keyguardUpdateMonitor.registerCallback(object : KeyguardUpdateMonitorCallback() { + override fun onStrongAuthStateChanged(userId: Int) { + notifyStateChanged("onStrongAuthStateChanged") + } + }) + + // register lockscreen settings changed callbacks: + val settingsObserver: ContentObserver = object : ContentObserver(handler) { + override fun onChange(selfChange: Boolean, uri: Uri) { + if (keyguardStateController.isShowing) { + notifyStateChanged("Settings $uri changed") + } + } + } + + mContext.contentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), + false, + settingsObserver, + UserHandle.USER_ALL) + + mContext.contentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), + true, + settingsObserver, + UserHandle.USER_ALL) + + mContext.contentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.ZEN_MODE), + false, + settingsObserver) + + mContext.contentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS), + false, + settingsObserver, + UserHandle.USER_ALL) + + // register (maybe) public mode changed callbacks: + statusBarStateController.addCallback(object : StatusBarStateController.StateListener { + override fun onStateChanged(state: Int) { + notifyStateChanged("onStatusBarStateChanged") + } + }) + broadcastDispatcher.registerReceiver(object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (keyguardStateController.isShowing()) { + // maybe public mode changed + notifyStateChanged(intent.action) + } + } + }, IntentFilter(Intent.ACTION_USER_SWITCHED)) + } + + fun addOnStateChangedListener(listener: Consumer<String>) { + onStateChangedListeners.addIfAbsent(listener) + } + + fun removeOnStateChangedListener(listener: Consumer<String>) { + onStateChangedListeners.remove(listener) + } + + private fun notifyStateChanged(reason: String) { + onStateChangedListeners.forEach({ it.accept(reason) }) + } + + /** + * Determines if the given notification should be hidden based on the current keyguard state. + * If Listener#onKeyguardStateChanged is invoked, the results of this method may no longer + * be valid, and so should be re-queried + */ + fun hideNotification(entry: NotificationEntry): Boolean { + val sbn = entry.sbn + // FILTER OUT the notification when the keyguard is showing and... + if (keyguardStateController.isShowing()) { + // ... user settings or the device policy manager doesn't allow lockscreen + // notifications; + if (!lockscreenUserManager.shouldShowLockscreenNotifications()) { + return true + } + val currUserId: Int = lockscreenUserManager.getCurrentUserId() + val notifUserId = + if (sbn.user.identifier == UserHandle.USER_ALL) currUserId + else sbn.user.identifier + + // ... user is in lockdown + if (keyguardUpdateMonitor.isUserInLockdown(currUserId) || + keyguardUpdateMonitor.isUserInLockdown(notifUserId)) { + return true + } + + // ... device is in public mode and the user's settings doesn't allow + // notifications to show in public mode + if (lockscreenUserManager.isLockscreenPublicMode(currUserId) || + lockscreenUserManager.isLockscreenPublicMode(notifUserId)) { + if (entry.ranking.lockscreenVisibilityOverride == Notification.VISIBILITY_SECRET) { + return true + } + if (!lockscreenUserManager.userAllowsNotificationsInPublic(currUserId) || + !lockscreenUserManager.userAllowsNotificationsInPublic( + notifUserId)) { + return true + } + } + + // ... neither this notification nor its group have high enough priority + // to be shown on the lockscreen + if (entry.parent != null) { + val parent = entry.parent + if (priorityExceedsLockscreenShowingThreshold(parent)) { + return false + } + } + return !priorityExceedsLockscreenShowingThreshold(entry) + } + return false + } + + private fun priorityExceedsLockscreenShowingThreshold(entry: ListEntry?): Boolean = + when { + entry == null -> false + hideSilentNotificationsOnLockscreen -> highPriorityProvider.isHighPriority(entry) + else -> entry.representativeEntry?.ranking?.isAmbient == false + } + + private fun readShowSilentNotificationSetting() { + hideSilentNotificationsOnLockscreen = Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, + 1) == 0 + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt index c991376c9e36..6c99e3adb73e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt @@ -211,6 +211,14 @@ class NotificationInterruptLogger @Inject constructor( "Pulsing: $str1" }) } + + fun keyguardHideNotification(key: String) { + hunBuffer.log(TAG, DEBUG, { + str1 = key + }, { + "Keyguard Hide Notification: $str1" + }) + } } private const val TAG = "InterruptionStateProvider" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index 7ed2699b1068..c1771ccce9d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -36,6 +36,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.policy.BatteryController; @@ -66,6 +67,8 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter private final ContentObserver mHeadsUpObserver; private final HeadsUpManager mHeadsUpManager; private final NotificationInterruptLogger mLogger; + private final NotifPipelineFlags mFlags; + private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; @VisibleForTesting protected boolean mUseHeadsUp = false; @@ -81,7 +84,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter StatusBarStateController statusBarStateController, HeadsUpManager headsUpManager, NotificationInterruptLogger logger, - @Main Handler mainHandler) { + @Main Handler mainHandler, + NotifPipelineFlags flags, + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { mContentResolver = contentResolver; mPowerManager = powerManager; mDreamManager = dreamManager; @@ -91,6 +96,8 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter mStatusBarStateController = statusBarStateController; mHeadsUpManager = headsUpManager; mLogger = logger; + mFlags = flags; + mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider; mHeadsUpObserver = new ContentObserver(mainHandler) { @Override public void onChange(boolean selfChange) { @@ -282,7 +289,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter private boolean canAlertCommon(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); - if (mNotificationFilter.shouldFilterOut(entry)) { + if (!mFlags.isNewPipelineEnabled() && mNotificationFilter.shouldFilterOut(entry)) { mLogger.logNoAlertingFilteredOut(sbn); return false; } @@ -305,6 +312,11 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter return false; } + if (mKeyguardNotificationVisibilityProvider.hideNotification(entry)) { + mLogger.keyguardHideNotification(entry.getKey()); + return false; + } + return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 7df8e7df486e..6bbecc8438bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -1233,10 +1233,6 @@ public class NotificationStackScrollLayoutController { mView.forceNoOverlappingRendering(force); } - public void setTranslationX(float translation) { - mView.setTranslationX(translation); - } - public void setExpandingVelocity(float velocity) { mView.setExpandingVelocity(velocity); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index dc1af362ec23..7f1611fec551 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -555,6 +555,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mControlsButton.setImageResource(mControlsComponent.getTileImageId()); mControlsButton.setContentDescription(getContext() .getString(mControlsComponent.getTileTitleId())); + updateAffordanceColors(); boolean hasFavorites = mControlsComponent.getControlsController() .map(c -> c.getFavorites().size() > 0) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt index e4161a37e52e..7764d33856ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt @@ -234,7 +234,7 @@ class NotificationsQSContainerController @Inject constructor( val endConstraintId = if (splitShadeEnabled) R.id.qs_edge_guideline else PARENT_ID constraintSet.apply { connect(R.id.qs_frame, END, endConstraintId, END) - setMargin(R.id.qs_frame, START, panelMarginHorizontal) + setMargin(R.id.qs_frame, START, if (splitShadeEnabled) 0 else panelMarginHorizontal) setMargin(R.id.qs_frame, END, if (splitShadeEnabled) 0 else panelMarginHorizontal) setMargin(R.id.qs_frame, TOP, topMargin) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java index ad47e2bc44a8..01fe8657fe47 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy; +import android.annotation.WorkerThread; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -219,6 +220,7 @@ public class FlashlightControllerImpl implements FlashlightController { new CameraManager.TorchCallback() { @Override + @WorkerThread public void onTorchModeUnavailable(String cameraId) { if (TextUtils.equals(cameraId, mCameraId)) { setCameraAvailable(false); @@ -229,6 +231,7 @@ public class FlashlightControllerImpl implements FlashlightController { } @Override + @WorkerThread public void onTorchModeChanged(String cameraId, boolean enabled) { if (TextUtils.equals(cameraId, mCameraId)) { setCameraAvailable(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index fa26a356f191..763f0417cac8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -67,6 +67,7 @@ import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -122,6 +123,7 @@ public class UserSwitcherController implements Dumpable { protected final Handler mHandler; private final ActivityStarter mActivityStarter; private final BroadcastDispatcher mBroadcastDispatcher; + private final BroadcastSender mBroadcastSender; private final TelephonyListenerManager mTelephonyListenerManager; private final InteractionJankMonitor mInteractionJankMonitor; private final LatencyTracker mLatencyTracker; @@ -165,6 +167,7 @@ public class UserSwitcherController implements Dumpable { @Main Handler handler, ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher, + BroadcastSender broadcastSender, UiEventLogger uiEventLogger, FalsingManager falsingManager, TelephonyListenerManager telephonyListenerManager, @@ -179,6 +182,7 @@ public class UserSwitcherController implements Dumpable { mActivityManager = activityManager; mUserTracker = userTracker; mBroadcastDispatcher = broadcastDispatcher; + mBroadcastSender = broadcastSender; mTelephonyListenerManager = telephonyListenerManager; mUiEventLogger = uiEventLogger; mFalsingManager = falsingManager; @@ -1194,7 +1198,7 @@ public class UserSwitcherController implements Dumpable { } // Use broadcast instead of ShadeController, as this dialog may have started in // another process and normal dagger bindings are not available - getContext().sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + mBroadcastSender.closeSystemDialogs(); getContext().startActivityAsUser( CreateUserActivity.createIntentForStart(getContext()), mUserTracker.getUserHandle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewBoundAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewBoundAnimatorTest.kt new file mode 100644 index 000000000000..214fd4d28398 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewBoundAnimatorTest.kt @@ -0,0 +1,277 @@ +package com.android.systemui.animation + +import android.animation.ObjectAnimator +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import junit.framework.Assert.assertEquals +import junit.framework.Assert.assertNotNull +import junit.framework.Assert.assertNull +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class ViewBoundAnimatorTest : SysuiTestCase() { + companion object { + private const val TEST_DURATION = 1000L + private val TEST_INTERPOLATOR = Interpolators.LINEAR + } + + private lateinit var rootView: LinearLayout + + @Before + fun setUp() { + rootView = LinearLayout(mContext) + } + + @After + fun tearDown() { + ViewBoundAnimator.stopAnimating(rootView) + } + + @Test + fun respectsAnimationParameters() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate( + rootView, interpolator = TEST_INTERPOLATOR, duration = TEST_DURATION + ) + rootView.layout(0 /* l */, 0 /* t */, 100 /* r */, 100 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + val animator = rootView.getTag(R.id.tag_animator) as ObjectAnimator + assertEquals(animator.interpolator, TEST_INTERPOLATOR) + assertEquals(animator.duration, TEST_DURATION) + } + + @Test + fun animatesFromStartToEnd() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate(rootView) + // Change all bounds. + rootView.layout(0 /* l */, 15 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + // The initial values should be those of the previous layout. + checkBounds(rootView, l = 10, t = 10, r = 50, b = 50) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + // The end values should be those of the latest layout. + checkBounds(rootView, l = 0, t = 15, r = 70, b = 80) + } + + @Test + fun animatesSuccessiveLayoutChanges() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate(rootView) + // Change all bounds. + rootView.layout(0 /* l */, 15 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 0, t = 15, r = 70, b = 80) + + // Change only top and right. + rootView.layout(0 /* l */, 20 /* t */, 60 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 0, t = 20, r = 60, b = 80) + + // Change all bounds again. + rootView.layout(5 /* l */, 25 /* t */, 55 /* r */, 95 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 5, t = 25, r = 55, b = 95) + } + + @Test + fun animatesFromPreviousAnimationProgress() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animateNextUpdate(rootView, interpolator = TEST_INTERPOLATOR) + // Change all bounds. + rootView.layout(0 /* l */, 20 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + advanceAnimation(rootView, fraction = 0.5f) + checkBounds(rootView, l = 5, t = 15, r = 60, b = 65) + + // Change all bounds again. + rootView.layout(25 /* l */, 25 /* t */, 55 /* r */, 60 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 5, t = 15, r = 60, b = 65) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 25, t = 25, r = 55, b = 60) + } + + @Test + fun animatesRootAndChildren() { + val firstChild = View(mContext) + rootView.addView(firstChild) + val secondChild = View(mContext) + rootView.addView(secondChild) + rootView.layout(0 /* l */, 0 /* t */, 150 /* r */, 100 /* b */) + firstChild.layout(0 /* l */, 0 /* t */, 100 /* r */, 100 /* b */) + secondChild.layout(100 /* l */, 0 /* t */, 150 /* r */, 100 /* b */) + + ViewBoundAnimator.animate(rootView) + // Change all bounds. + rootView.layout(10 /* l */, 20 /* t */, 200 /* r */, 120 /* b */) + firstChild.layout(10 /* l */, 20 /* t */, 150 /* r */, 120 /* b */) + secondChild.layout(150 /* l */, 20 /* t */, 200 /* r */, 120 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + // The initial values should be those of the previous layout. + checkBounds(rootView, l = 0, t = 0, r = 150, b = 100) + checkBounds(firstChild, l = 0, t = 0, r = 100, b = 100) + checkBounds(secondChild, l = 100, t = 0, r = 150, b = 100) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + // The end values should be those of the latest layout. + checkBounds(rootView, l = 10, t = 20, r = 200, b = 120) + checkBounds(firstChild, l = 10, t = 20, r = 150, b = 120) + checkBounds(secondChild, l = 150, t = 20, r = 200, b = 120) + } + + @Test + fun doesNotAnimateInvisibleViews() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate(rootView) + // GONE. + rootView.visibility = View.GONE + rootView.layout(0 /* l */, 15 /* t */, 55 /* r */, 80 /* b */) + + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 0, t = 15, r = 55, b = 80) + + // INVISIBLE. + rootView.visibility = View.INVISIBLE + rootView.layout(0 /* l */, 20 /* t */, 0 /* r */, 20 /* b */) + } + + @Test + fun doesNotAnimateUnchangingBounds() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate(rootView) + // No bounds are changed. + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 10, t = 10, r = 50, b = 50) + + // Change only right and bottom. + rootView.layout(10 /* l */, 10 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 10, t = 10, r = 70, b = 80) + } + + @Test + fun doesNotAnimateExcludedBounds() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate( + rootView, + bounds = setOf(ViewBoundAnimator.Bound.LEFT, ViewBoundAnimator.Bound.TOP), + interpolator = TEST_INTERPOLATOR + ) + // Change all bounds. + rootView.layout(0 /* l */, 20 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + advanceAnimation(rootView, 0.5f) + checkBounds(rootView, l = 5, t = 15, r = 70, b = 80) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 0, t = 20, r = 70, b = 80) + } + + @Test + fun stopsAnimatingAfterSingleLayout() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animateNextUpdate(rootView) + // Change all bounds. + rootView.layout(0 /* l */, 15 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 0, t = 15, r = 70, b = 80) + + // Change all bounds again. + rootView.layout(10 /* l */, 10 /* t */, 50/* r */, 50 /* b */) + + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 10, t = 10, r = 50, b = 50) + } + + @Test + fun stopsAnimatingWhenInstructed() { + rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */) + + ViewBoundAnimator.animate(rootView) + // Change all bounds. + rootView.layout(0 /* l */, 15 /* t */, 70 /* r */, 80 /* b */) + + assertNotNull(rootView.getTag(R.id.tag_animator)) + endAnimation(rootView) + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 0, t = 15, r = 70, b = 80) + + ViewBoundAnimator.stopAnimating(rootView) + // Change all bounds again. + rootView.layout(10 /* l */, 10 /* t */, 50/* r */, 50 /* b */) + + assertNull(rootView.getTag(R.id.tag_animator)) + checkBounds(rootView, l = 10, t = 10, r = 50, b = 50) + } + + private fun checkBounds(v: View, l: Int, t: Int, r: Int, b: Int) { + assertEquals(l, v.left) + assertEquals(t, v.top) + assertEquals(r, v.right) + assertEquals(b, v.bottom) + } + + private fun advanceAnimation(rootView: View, fraction: Float) { + (rootView.getTag(R.id.tag_animator) as? ObjectAnimator)?.setCurrentFraction(fraction) + + if (rootView is ViewGroup) { + for (i in 0 until rootView.childCount) { + advanceAnimation(rootView.getChildAt(i), fraction) + } + } + } + + private fun endAnimation(rootView: View) { + (rootView.getTag(R.id.tag_animator) as? ObjectAnimator)?.end() + + if (rootView is ViewGroup) { + for (i in 0 until rootView.childCount) { + endAnimation(rootView.getChildAt(i)) + } + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt new file mode 100644 index 000000000000..fbd2c918648a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.broadcast + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.wakelock.WakeLockFake +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class BroadcastSenderTest : SysuiTestCase() { + + @Mock + private lateinit var mockContext: Context + + private lateinit var broadcastSender: BroadcastSender + private lateinit var executor: FakeExecutor + private lateinit var wakeLock: WakeLockFake + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + executor = FakeExecutor(FakeSystemClock()) + wakeLock = WakeLockFake() + val wakeLockBuilder = WakeLockFake.Builder(mContext) + wakeLockBuilder.setWakeLock(wakeLock) + broadcastSender = BroadcastSender(mockContext, wakeLockBuilder, executor) + } + + @Test + fun sendBroadcast_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + broadcastSender.sendBroadcast(intent) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcast(intent) + } + } + + @Test + fun sendBroadcastWithPermission_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + broadcastSender.sendBroadcast(intent, permission) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcast(intent, permission) + } + } + + @Test + fun sendBroadcastAsUser_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL) + } + } + + @Test + fun sendBroadcastAsUserWithPermission_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL, permission) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL, permission) + } + } + + @Test + fun sendBroadcastAsUserWithPermissionAndOptions_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + val options = Bundle() + options.putString("key", "value") + + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL, permission, options) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL, permission, options) + } + } + + @Test + fun sendBroadcastAsUserWithPermissionAndAppOp_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL, permission, 12) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL, permission, 12) + } + } + + @Test + fun sendCloseSystemDialogs_dispatchesWithWakelock() { + val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) + + broadcastSender.closeSystemDialogs() + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcast(intentCaptor.capture()) + assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) + } + } + + private fun runExecutorAssertingWakelock(verification: () -> Unit) { + assertThat(wakeLock.isHeld).isTrue() + executor.runAllReady() + verification.invoke() + assertThat(wakeLock.isHeld).isFalse() + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt index da25c6202b21..49eaf8239ca0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt @@ -23,6 +23,7 @@ import android.provider.Settings import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.VibratorHelper @@ -62,6 +63,8 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { @Mock private lateinit var activityStarter: ActivityStarter @Mock + private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var taskViewFactory: Optional<TaskViewFactory> @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var cvh: ControlViewHolder @@ -94,6 +97,7 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { bgExecutor, uiExecutor, activityStarter, + broadcastSender, keyguardStateController, taskViewFactory, metricsLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt index 87b9172dcefc..0166fa25d526 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt @@ -21,6 +21,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender import com.android.wm.shell.TaskView import org.junit.Before import org.junit.Test @@ -39,6 +40,8 @@ class DetailDialogTest : SysuiTestCase() { @Mock private lateinit var taskView: TaskView @Mock + private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var controlViewHolder: ControlViewHolder @Mock private lateinit var pendingIntent: PendingIntent @@ -63,6 +66,7 @@ class DetailDialogTest : SysuiTestCase() { private fun createDialog(pendingIntent: PendingIntent): DetailDialog { return DetailDialog( mContext, + broadcastSender, taskView, pendingIntent, controlViewHolder diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java index ff9e13a48bec..dcbdea0ac5a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java @@ -16,7 +16,6 @@ package com.android.systemui.dreams; -import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; @@ -30,7 +29,6 @@ import android.view.ViewTreeObserver; import androidx.test.filters.SmallTest; -import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.dreams.complication.ComplicationHostViewController; @@ -44,7 +42,6 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) public class DreamOverlayContainerViewControllerTest extends SysuiTestCase { - private static final int DREAM_OVERLAY_NOTIFICATIONS_DRAG_AREA_HEIGHT = 100; private static final int MAX_BURN_IN_OFFSET = 20; private static final long BURN_IN_PROTECTION_UPDATE_INTERVAL = 10; private static final long MILLIS_UNTIL_FULL_JITTER = 240 * 1000; @@ -76,9 +73,6 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase { public void setup() { MockitoAnnotations.initMocks(this); - when(mResources.getDimensionPixelSize( - R.dimen.dream_overlay_notifications_drag_area_height)).thenReturn( - DREAM_OVERLAY_NOTIFICATIONS_DRAG_AREA_HEIGHT); when(mDreamOverlayContainerView.getResources()).thenReturn(mResources); when(mDreamOverlayContainerView.getViewTreeObserver()).thenReturn(mViewTreeObserver); @@ -100,13 +94,6 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase { } @Test - public void testSetsDreamOverlayNotificationsDragAreaHeight() { - assertEquals( - mController.getDreamOverlayNotificationsDragAreaHeight(), - DREAM_OVERLAY_NOTIFICATIONS_DRAG_AREA_HEIGHT); - } - - @Test public void testBurnInProtectionStartsWhenContentViewAttached() { mController.onViewAttached(); verify(mHandler).postDelayed(any(Runnable.class), eq(BURN_IN_PROTECTION_UPDATE_INTERVAL)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java index 7d7ccb462b3e..3657192daede 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java @@ -174,19 +174,19 @@ public class DreamOverlayServiceTest extends SysuiTestCase { } @Test - public void testShouldShowComplicationsTrueByDefault() { + public void testShouldShowComplicationsFalseByDefault() { mService.onBind(new Intent()); - assertThat(mService.shouldShowComplications()).isTrue(); + assertThat(mService.shouldShowComplications()).isFalse(); } @Test public void testShouldShowComplicationsSetByIntentExtra() { final Intent intent = new Intent(); - intent.putExtra(DreamService.EXTRA_SHOW_COMPLICATIONS, false); + intent.putExtra(DreamService.EXTRA_SHOW_COMPLICATIONS, true); mService.onBind(intent); - assertThat(mService.shouldShowComplications()).isFalse(); + assertThat(mService.shouldShowComplications()).isTrue(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java index 49da4bd5a825..3ce9889571f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java @@ -158,6 +158,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { public void testComplicationFilteringWhenShouldShowComplications() { final DreamOverlayStateController stateController = new DreamOverlayStateController(mExecutor); + stateController.setShouldShowComplications(true); final Complication alwaysAvailableComplication = Mockito.mock(Complication.class); final Complication weatherComplication = Mockito.mock(Complication.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 708fc915410c..cb68d81287df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -40,6 +40,7 @@ import androidx.lifecycle.LiveData import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.media.dialog.MediaOutputDialogFactory import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager @@ -59,6 +60,7 @@ import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mock import org.mockito.Mockito.mock import org.mockito.Mockito.never +import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -85,6 +87,7 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var bgExecutor: FakeExecutor @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var broadcastSender: BroadcastSender @Mock private lateinit var holder: PlayerViewHolder @Mock private lateinit var sessionHolder: PlayerSessionViewHolder @@ -119,8 +122,6 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var actionPlayPause: ImageButton private lateinit var actionNext: ImageButton private lateinit var actionPrev: ImageButton - private lateinit var actionStart: ImageButton - private lateinit var actionEnd: ImageButton @Mock private lateinit var longPressText: TextView @Mock private lateinit var handler: Handler private lateinit var settings: View @@ -144,8 +145,8 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(mediaViewController.expandedLayout).thenReturn(expandedSet) whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet) - player = MediaControlPanel(context, bgExecutor, activityStarter, mediaViewController, - seekBarViewModel, Lazy { mediaDataManager }, + player = MediaControlPanel(context, bgExecutor, activityStarter, broadcastSender, + mediaViewController, seekBarViewModel, Lazy { mediaDataManager }, mediaOutputDialogFactory, mediaCarouselController, falsingManager, mediaFlags, clock) whenever(seekBarViewModel.progress).thenReturn(seekBarData) @@ -168,6 +169,17 @@ public class MediaControlPanelTest : SysuiTestCase() { cancelText = TextView(context) dismiss = FrameLayout(context) dismissText = TextView(context) + + action0 = ImageButton(context).also { it.setId(R.id.action0) } + action1 = ImageButton(context).also { it.setId(R.id.action1) } + action2 = ImageButton(context).also { it.setId(R.id.action2) } + action3 = ImageButton(context).also { it.setId(R.id.action3) } + action4 = ImageButton(context).also { it.setId(R.id.action4) } + + actionPlayPause = ImageButton(context).also { it.setId(R.id.actionPlayPause) } + actionPrev = ImageButton(context).also { it.setId(R.id.actionPrev) } + actionNext = ImageButton(context).also { it.setId(R.id.actionNext) } + initPlayerHolderMocks() initSessionHolderMocks() @@ -208,90 +220,64 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } - /** Mock view holder for the notification player */ - private fun initPlayerHolderMocks() { - whenever(holder.player).thenReturn(view) - whenever(holder.appIcon).thenReturn(appIcon) - whenever(holder.albumView).thenReturn(albumView) - whenever(holder.titleText).thenReturn(titleText) - whenever(holder.artistText).thenReturn(artistText) + /** + * Initialize elements common to both view holders + */ + private fun initMediaViewHolderMocks(viewHolder: MediaViewHolder) { + whenever(viewHolder.player).thenReturn(view) + whenever(viewHolder.appIcon).thenReturn(appIcon) + whenever(viewHolder.albumView).thenReturn(albumView) + whenever(viewHolder.titleText).thenReturn(titleText) + whenever(viewHolder.artistText).thenReturn(artistText) whenever(seamlessBackground.getDrawable(0)).thenReturn(mock(GradientDrawable::class.java)) - whenever(holder.seamless).thenReturn(seamless) - whenever(holder.seamlessButton).thenReturn(seamlessButton) - whenever(holder.seamlessIcon).thenReturn(seamlessIcon) - whenever(holder.seamlessText).thenReturn(seamlessText) - whenever(holder.seekBar).thenReturn(seekBar) - whenever(holder.elapsedTimeView).thenReturn(elapsedTimeView) - whenever(holder.totalTimeView).thenReturn(totalTimeView) + whenever(viewHolder.seamless).thenReturn(seamless) + whenever(viewHolder.seamlessButton).thenReturn(seamlessButton) + whenever(viewHolder.seamlessIcon).thenReturn(seamlessIcon) + whenever(viewHolder.seamlessText).thenReturn(seamlessText) + whenever(viewHolder.seekBar).thenReturn(seekBar) // Action buttons - action0 = ImageButton(context) - whenever(holder.action0).thenReturn(action0) - whenever(holder.getAction(R.id.action0)).thenReturn(action0) - action1 = ImageButton(context) - whenever(holder.action1).thenReturn(action1) - whenever(holder.getAction(R.id.action1)).thenReturn(action1) - action2 = ImageButton(context) - whenever(holder.action2).thenReturn(action2) - whenever(holder.getAction(R.id.action2)).thenReturn(action2) - action3 = ImageButton(context) - whenever(holder.action3).thenReturn(action3) - whenever(holder.getAction(R.id.action3)).thenReturn(action3) - action4 = ImageButton(context) - whenever(holder.action4).thenReturn(action4) - whenever(holder.getAction(R.id.action4)).thenReturn(action4) + whenever(viewHolder.action0).thenReturn(action0) + whenever(viewHolder.getAction(R.id.action0)).thenReturn(action0) + whenever(viewHolder.action1).thenReturn(action1) + whenever(viewHolder.getAction(R.id.action1)).thenReturn(action1) + whenever(viewHolder.action2).thenReturn(action2) + whenever(viewHolder.getAction(R.id.action2)).thenReturn(action2) + whenever(viewHolder.action3).thenReturn(action3) + whenever(viewHolder.getAction(R.id.action3)).thenReturn(action3) + whenever(viewHolder.action4).thenReturn(action4) + whenever(viewHolder.getAction(R.id.action4)).thenReturn(action4) // Long press menu - whenever(holder.longPressText).thenReturn(longPressText) + whenever(viewHolder.longPressText).thenReturn(longPressText) whenever(longPressText.handler).thenReturn(handler) - whenever(holder.settings).thenReturn(settings) - whenever(holder.settingsText).thenReturn(settingsText) - whenever(holder.cancel).thenReturn(cancel) - whenever(holder.cancelText).thenReturn(cancelText) - whenever(holder.dismiss).thenReturn(dismiss) - whenever(holder.dismissText).thenReturn(dismissText) + whenever(viewHolder.settings).thenReturn(settings) + whenever(viewHolder.settingsText).thenReturn(settingsText) + whenever(viewHolder.cancel).thenReturn(cancel) + whenever(viewHolder.cancelText).thenReturn(cancelText) + whenever(viewHolder.dismiss).thenReturn(dismiss) + whenever(viewHolder.dismissText).thenReturn(dismissText) + } + + /** Mock view holder for the notification player */ + private fun initPlayerHolderMocks() { + initMediaViewHolderMocks(holder) + + whenever(holder.elapsedTimeView).thenReturn(elapsedTimeView) + whenever(holder.totalTimeView).thenReturn(totalTimeView) } /** Mock view holder for session player */ private fun initSessionHolderMocks() { - whenever(sessionHolder.player).thenReturn(view) - whenever(sessionHolder.albumView).thenReturn(albumView) - whenever(sessionHolder.appIcon).thenReturn(appIcon) - whenever(sessionHolder.titleText).thenReturn(titleText) - whenever(sessionHolder.artistText).thenReturn(artistText) - val seamlessBackground = mock(RippleDrawable::class.java) - whenever(seamlessBackground.getDrawable(0)).thenReturn(mock(GradientDrawable::class.java)) - whenever(sessionHolder.seamless).thenReturn(seamless) - whenever(sessionHolder.seamlessButton).thenReturn(seamlessButton) - whenever(sessionHolder.seamlessIcon).thenReturn(seamlessIcon) - whenever(sessionHolder.seamlessText).thenReturn(seamlessText) - whenever(sessionHolder.seekBar).thenReturn(seekBar) + initMediaViewHolderMocks(sessionHolder) - // Action buttons - actionPlayPause = ImageButton(context) + // Semantic action buttons whenever(sessionHolder.actionPlayPause).thenReturn(actionPlayPause) whenever(sessionHolder.getAction(R.id.actionPlayPause)).thenReturn(actionPlayPause) - actionNext = ImageButton(context) whenever(sessionHolder.actionNext).thenReturn(actionNext) whenever(sessionHolder.getAction(R.id.actionNext)).thenReturn(actionNext) - actionPrev = ImageButton(context) whenever(sessionHolder.actionPrev).thenReturn(actionPrev) whenever(sessionHolder.getAction(R.id.actionPrev)).thenReturn(actionPrev) - actionStart = ImageButton(context) - whenever(sessionHolder.actionStart).thenReturn(actionStart) - whenever(sessionHolder.getAction(R.id.actionStart)).thenReturn(actionStart) - actionEnd = ImageButton(context) - whenever(sessionHolder.actionEnd).thenReturn(actionEnd) - whenever(sessionHolder.getAction(R.id.actionEnd)).thenReturn(actionEnd) - - // Long press menu - whenever(sessionHolder.longPressText).thenReturn(longPressText) - whenever(sessionHolder.settings).thenReturn(settings) - whenever(sessionHolder.settingsText).thenReturn(settingsText) - whenever(sessionHolder.cancel).thenReturn(cancel) - whenever(sessionHolder.cancelText).thenReturn(cancelText) - whenever(sessionHolder.dismiss).thenReturn(dismiss) - whenever(sessionHolder.dismissText).thenReturn(dismissText) } @After @@ -316,8 +302,8 @@ public class MediaControlPanelTest : SysuiTestCase() { val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), nextOrCustom = MediaAction(icon, Runnable {}, "next"), - startCustom = MediaAction(icon, null, "custom 1"), - endCustom = MediaAction(icon, null, "custom 2") + custom0 = MediaAction(icon, null, "custom 0"), + custom1 = MediaAction(icon, null, "custom 1") ) val state = mediaData.copy(semanticActions = semanticActions) @@ -325,7 +311,7 @@ public class MediaControlPanelTest : SysuiTestCase() { player.bindPlayer(state, PACKAGE) verify(expandedSet).setVisibility(R.id.action0, ConstraintSet.VISIBLE) - assertThat(action0.contentDescription).isEqualTo("custom 1") + assertThat(action0.contentDescription).isEqualTo("custom 0") assertThat(action0.isEnabled()).isFalse() verify(expandedSet).setVisibility(R.id.action1, ConstraintSet.INVISIBLE) @@ -340,7 +326,7 @@ public class MediaControlPanelTest : SysuiTestCase() { assertThat(action3.contentDescription).isEqualTo("next") verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.VISIBLE) - assertThat(action4.contentDescription).isEqualTo("custom 2") + assertThat(action4.contentDescription).isEqualTo("custom 1") assertThat(action4.isEnabled()).isFalse() } @@ -353,28 +339,96 @@ public class MediaControlPanelTest : SysuiTestCase() { val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), nextOrCustom = MediaAction(icon, Runnable {}, "next"), - startCustom = MediaAction(icon, null, "custom 1"), - endCustom = MediaAction(icon, null, "custom 2") + custom0 = MediaAction(icon, null, "custom 0"), + custom1 = MediaAction(icon, null, "custom 1") ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(sessionHolder, MediaViewController.TYPE.PLAYER_SESSION) player.bindPlayer(state, PACKAGE) - assertThat(actionStart.contentDescription).isEqualTo("custom 1") - assertThat(actionStart.isEnabled()).isFalse() - assertThat(actionPrev.isEnabled()).isFalse() assertThat(actionPrev.drawable).isNull() + verify(collapsedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) assertThat(actionPlayPause.isEnabled()).isTrue() assertThat(actionPlayPause.contentDescription).isEqualTo("play") + verify(collapsedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.VISIBLE) assertThat(actionNext.isEnabled()).isTrue() assertThat(actionNext.contentDescription).isEqualTo("next") + verify(collapsedSet).setVisibility(R.id.actionNext, ConstraintSet.VISIBLE) + + // Called twice since these IDs are used as generic buttons + assertThat(action0.contentDescription).isEqualTo("custom 0") + assertThat(action0.isEnabled()).isFalse() + verify(collapsedSet, times(2)).setVisibility(R.id.action0, ConstraintSet.GONE) + + assertThat(action1.contentDescription).isEqualTo("custom 1") + assertThat(action1.isEnabled()).isFalse() + verify(collapsedSet, times(2)).setVisibility(R.id.action1, ConstraintSet.GONE) + + // Verify generic buttons are hidden + verify(collapsedSet).setVisibility(R.id.action2, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.action2, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.action3, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.action3, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.action4, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.GONE) + } + + @Test + fun bindNotificationActionsNewLayout() { + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) + + val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) + val actions = listOf( + MediaAction(icon, Runnable {}, "previous"), + MediaAction(icon, Runnable {}, "play"), + MediaAction(icon, null, "next"), + MediaAction(icon, null, "custom 0"), + MediaAction(icon, Runnable {}, "custom 1") + ) + val state = mediaData.copy(actions = actions, + actionsToShowInCompact = listOf(1, 2), + semanticActions = null) + + player.attachPlayer(sessionHolder, MediaViewController.TYPE.PLAYER_SESSION) + player.bindPlayer(state, PACKAGE) + + // Verify semantic actions are hidden + verify(collapsedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.actionNext, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.actionNext, ConstraintSet.GONE) + + // Generic actions all enabled + assertThat(action0.contentDescription).isEqualTo("previous") + assertThat(action0.isEnabled()).isTrue() + verify(collapsedSet).setVisibility(R.id.action0, ConstraintSet.GONE) + + assertThat(action1.contentDescription).isEqualTo("play") + assertThat(action1.isEnabled()).isTrue() + verify(collapsedSet).setVisibility(R.id.action1, ConstraintSet.VISIBLE) + + assertThat(action2.contentDescription).isEqualTo("next") + assertThat(action2.isEnabled()).isFalse() + verify(collapsedSet).setVisibility(R.id.action2, ConstraintSet.VISIBLE) + + assertThat(action3.contentDescription).isEqualTo("custom 0") + assertThat(action3.isEnabled()).isFalse() + verify(collapsedSet).setVisibility(R.id.action3, ConstraintSet.GONE) - assertThat(actionEnd.contentDescription).isEqualTo("custom 2") - assertThat(actionEnd.isEnabled()).isFalse() + assertThat(action4.contentDescription).isEqualTo("custom 1") + assertThat(action4.isEnabled()).isTrue() + verify(collapsedSet).setVisibility(R.id.action4, ConstraintSet.GONE) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index 6b203bcf6828..82a48efafa3a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -23,6 +23,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -65,6 +66,8 @@ class MediaDataFilterTest : SysuiTestCase() { @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher @Mock + private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var mediaResumeListener: MediaResumeListener @Mock private lateinit var mediaDataManager: MediaDataManager @@ -87,7 +90,7 @@ class MediaDataFilterTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) MediaPlayerData.clear() - mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, + mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, broadcastSender, lockscreenUserManager, executor, clock) mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.addListener(listener) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index 021f70e05b32..925ae30e8773 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -659,11 +659,11 @@ class MediaDataManagerTest : SysuiTestCase() { actions.nextOrCustom!!.action!!.run() verify(transportControls).skipToNext() - assertThat(actions.startCustom).isNotNull() - assertThat(actions.startCustom!!.contentDescription).isEqualTo(customDesc[0]) + assertThat(actions.custom0).isNotNull() + assertThat(actions.custom0!!.contentDescription).isEqualTo(customDesc[0]) - assertThat(actions.endCustom).isNotNull() - assertThat(actions.endCustom!!.contentDescription).isEqualTo(customDesc[1]) + assertThat(actions.custom1).isNotNull() + assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[1]) } @Test @@ -697,11 +697,11 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(actions.nextOrCustom).isNotNull() assertThat(actions.nextOrCustom!!.contentDescription).isEqualTo(customDesc[1]) - assertThat(actions.startCustom).isNotNull() - assertThat(actions.startCustom!!.contentDescription).isEqualTo(customDesc[2]) + assertThat(actions.custom0).isNotNull() + assertThat(actions.custom0!!.contentDescription).isEqualTo(customDesc[2]) - assertThat(actions.endCustom).isNotNull() - assertThat(actions.endCustom!!.contentDescription).isEqualTo(customDesc[3]) + assertThat(actions.custom1).isNotNull() + assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[3]) } @Test @@ -737,10 +737,10 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(actions.prevOrCustom).isNull() assertThat(actions.nextOrCustom).isNull() - assertThat(actions.startCustom).isNotNull() - assertThat(actions.startCustom!!.contentDescription).isEqualTo(customDesc[0]) + assertThat(actions.custom0).isNotNull() + assertThat(actions.custom0!!.contentDescription).isEqualTo(customDesc[0]) - assertThat(actions.endCustom).isNotNull() - assertThat(actions.endCustom!!.contentDescription).isEqualTo(customDesc[1]) + assertThat(actions.custom1).isNotNull() + assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[1]) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index 13e582196ffb..380fa6d50df7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -37,15 +37,14 @@ import android.widget.TextView; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.ShadeController; import org.junit.Before; import org.junit.Test; @@ -64,11 +63,10 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private MediaOutputBaseAdapter mMediaOutputBaseAdapter = mock(MediaOutputBaseAdapter.class); private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private ShadeController mShadeController = mock(ShadeController.class); private ActivityStarter mStarter = mock(ActivityStarter.class); + private BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); - private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); @@ -77,17 +75,16 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private MediaOutputController mMediaOutputController; private int mHeaderIconRes; private IconCompat mIconCompat; - private Drawable mAppSourceDrawable; private CharSequence mHeaderTitle; private CharSequence mHeaderSubtitle; @Before public void setUp() { - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotificationEntryManager, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); - mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, + mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); } @@ -178,15 +175,16 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog { - MediaOutputBaseDialogImpl(Context context, MediaOutputController mediaOutputController) { - super(context, mediaOutputController); + MediaOutputBaseDialogImpl(Context context, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController) { + super(context, broadcastSender, mediaOutputController); mAdapter = mMediaOutputBaseAdapter; } @Override Drawable getAppSourceIcon() { - return mAppSourceDrawable; + return null; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 6230700a6a2e..d2dae745bcdc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -45,7 +45,6 @@ import android.text.TextUtils; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; @@ -57,7 +56,6 @@ import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; -import com.android.systemui.statusbar.phone.ShadeController; import com.google.common.collect.ImmutableList; @@ -96,10 +94,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { private NearbyDevice mNearbyDevice2 = mock(NearbyDevice.class); private MediaMetadata mMediaMetadata = mock(MediaMetadata.class); private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class); - private ShadeController mShadeController = mock(ShadeController.class); private ActivityStarter mStarter = mock(ActivityStarter.class); private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class); - private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); @@ -124,9 +120,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn( mCachedBluetoothDeviceManager); - mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; @@ -176,9 +172,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void start_withoutPackageName_verifyMediaControllerInit() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.start(mCb); @@ -205,9 +201,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void stop_withoutPackageName_verifyMediaControllerDeinit() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.start(mCb); @@ -510,9 +506,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getNotificationLargeIcon_withoutPackageName_returnsNull() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index cb52e7c20464..db56f875dd5c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -37,10 +37,10 @@ import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.ShadeController; import org.junit.After; import org.junit.Before; @@ -61,8 +61,8 @@ public class MediaOutputDialogTest extends SysuiTestCase { // Mock private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private final ShadeController mShadeController = mock(ShadeController.class); private final ActivityStarter mStarter = mock(ActivityStarter.class); + private final BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private final LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); private final MediaDevice mMediaDevice = mock(MediaDevice.class); private final NotificationEntryManager mNotificationEntryManager = @@ -78,12 +78,12 @@ public class MediaOutputDialogTest extends SysuiTestCase { @Before public void setUp() { - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotificationEntryManager, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputDialog = new MediaOutputDialog(mContext, false, + mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender, mMediaOutputController, mUiEventLogger); mMediaOutputDialog.show(); @@ -129,7 +129,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { // Check the visibility metric logging by creating a new MediaOutput dialog, // and verify if the calling times increases. public void onCreate_ShouldLogVisibility() { - MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false, + MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false, mBroadcastSender, mMediaOutputController, mUiEventLogger); testDialog.show(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java index f186f57fd0e5..0cdde0775b2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java @@ -28,17 +28,16 @@ import android.view.View; import androidx.test.filters.SmallTest; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.ShadeController; import org.junit.After; import org.junit.Before; @@ -59,14 +58,13 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { // Mock private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private ShadeController mShadeController = mock(ShadeController.class); private ActivityStarter mStarter = mock(ActivityStarter.class); + private BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); private MediaDevice mMediaDevice = mock(MediaDevice.class); private MediaDevice mMediaDevice1 = mock(MediaDevice.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); - private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); @@ -77,12 +75,12 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { @Before public void setUp() { - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotificationEntryManager, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, + mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender, mMediaOutputController); mMediaOutputGroupDialog.show(); when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mMediaDevices); diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java index afb63ab0ebcf..a156820ad141 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java @@ -37,6 +37,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.util.NotificationChannels; @@ -59,7 +60,9 @@ public class PowerNotificationWarningsTest extends SysuiTestCase { // Test Instance. mContext.addMockSystemService(NotificationManager.class, mMockNotificationManager); ActivityStarter starter = mDependency.injectMockDependency(ActivityStarter.class); - mPowerNotificationWarnings = new PowerNotificationWarnings(mContext, starter); + BroadcastSender broadcastSender = mDependency.injectMockDependency(BroadcastSender.class); + mPowerNotificationWarnings = new PowerNotificationWarnings(mContext, starter, + broadcastSender); BatteryStateSnapshot snapshot = new BatteryStateSnapshot(100, false, false, 1, BatteryManager.BATTERY_HEALTH_GOOD, 5, 15); mPowerNotificationWarnings.updateSnapshot(snapshot); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java index d0947497f0ec..ca8529d5cb03 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java @@ -16,18 +16,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator; -import static android.app.Notification.VISIBILITY_PUBLIC; -import static android.app.Notification.VISIBILITY_SECRET; -import static android.app.NotificationManager.IMPORTANCE_HIGH; -import static android.app.NotificationManager.IMPORTANCE_MIN; - -import static com.android.systemui.statusbar.notification.collection.EntryUtilKt.modifyEntry; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.os.Handler; import android.os.UserHandle; @@ -39,20 +29,16 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider; -import com.android.systemui.statusbar.notification.collection.GroupEntry; -import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; -import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -66,13 +52,13 @@ public class KeyguardCoordinatorTest extends SysuiTestCase { @Mock private Handler mMainHandler; @Mock private KeyguardStateController mKeyguardStateController; - @Mock private NotificationLockscreenUserManager mLockscreenUserManager; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock private StatusBarStateController mStatusBarStateController; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock private HighPriorityProvider mHighPriorityProvider; @Mock private SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider; @Mock private NotifPipeline mNotifPipeline; + @Mock private KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; private NotificationEntry mEntry; private NotifFilter mKeyguardFilter; @@ -81,9 +67,9 @@ public class KeyguardCoordinatorTest extends SysuiTestCase { public void setup() { MockitoAnnotations.initMocks(this); KeyguardCoordinator keyguardCoordinator = new KeyguardCoordinator( - mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager, - mBroadcastDispatcher, mStatusBarStateController, - mKeyguardUpdateMonitor, mHighPriorityProvider, mSectionHeaderVisibilityProvider); + mStatusBarStateController, + mKeyguardUpdateMonitor, mHighPriorityProvider, mSectionHeaderVisibilityProvider, + mKeyguardNotificationVisibilityProvider); mEntry = new NotificationEntryBuilder() .setUser(new UserHandle(NOTIF_USER_ID)) @@ -94,171 +80,4 @@ public class KeyguardCoordinatorTest extends SysuiTestCase { verify(mNotifPipeline, times(1)).addFinalizeFilter(filterCaptor.capture()); mKeyguardFilter = filterCaptor.getValue(); } - - @Test - public void unfilteredState() { - // GIVEN an 'unfiltered-keyguard-showing' state - setupUnfilteredState(mEntry); - - // THEN don't filter out the entry - assertFalse(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void keyguardNotShowing() { - // GIVEN the lockscreen isn't showing - setupUnfilteredState(mEntry); - when(mKeyguardStateController.isShowing()).thenReturn(false); - - // THEN don't filter out the entry - assertFalse(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void doNotShowLockscreenNotifications() { - // GIVEN an 'unfiltered-keyguard-showing' state - setupUnfilteredState(mEntry); - - // WHEN we shouldn't show any lockscreen notifications - when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false); - - // THEN filter out the entry - assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void lockdown() { - // GIVEN an 'unfiltered-keyguard-showing' state - setupUnfilteredState(mEntry); - - // WHEN the notification's user is in lockdown: - when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true); - - // THEN filter out the entry - assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void publicMode_settingsDisallow() { - // GIVEN an 'unfiltered-keyguard-showing' state - setupUnfilteredState(mEntry); - - // WHEN the notification's user is in public mode and settings are configured to disallow - // notifications in public mode - when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true); - when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID)) - .thenReturn(false); - - // THEN filter out the entry - assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void publicMode_notifDisallowed() { - // GIVEN an 'unfiltered-keyguard-showing' state - setupUnfilteredState(mEntry); - - // WHEN the notification's user is in public mode and settings are configured to disallow - // notifications in public mode - when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true); - mEntry.setRanking(new RankingBuilder() - .setKey(mEntry.getKey()) - .setVisibilityOverride(VISIBILITY_SECRET).build()); - - // THEN filter out the entry - assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void doesNotExceedThresholdToShow() { - // GIVEN an 'unfiltered-keyguard-showing' state - setupUnfilteredState(mEntry); - - // WHEN the notification doesn't exceed the threshold to show on the lockscreen - mEntry.setRanking(new RankingBuilder() - .setKey(mEntry.getKey()) - .setImportance(IMPORTANCE_MIN) - .build()); - when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); - - // THEN filter out the entry - assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); - } - - @Test - public void summaryExceedsThresholdToShow() { - // GIVEN the notification doesn't exceed the threshold to show on the lockscreen - // but it's part of a group (has a parent) - final NotificationEntry entryWithParent = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .build(); - - final GroupEntry parent = new GroupEntryBuilder() - .setKey("test_group_key") - .setSummary(new NotificationEntryBuilder() - .setImportance(IMPORTANCE_HIGH) - .build()) - .addChild(entryWithParent) - .build(); - - setupUnfilteredState(entryWithParent); - entryWithParent.setRanking(new RankingBuilder() - .setKey(entryWithParent.getKey()) - .setImportance(IMPORTANCE_MIN) - .build()); - - // WHEN its parent does exceed threshold tot show on the lockscreen - when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true); - - // THEN don't filter out the entry - assertFalse(mKeyguardFilter.shouldFilterOut(entryWithParent, 0)); - - // WHEN its parent doesn't exceed threshold to show on lockscreen - when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false); - modifyEntry(parent.getSummary(), builder -> builder - .setImportance(IMPORTANCE_MIN) - .done()); - - // THEN filter out the entry - assertTrue(mKeyguardFilter.shouldFilterOut(entryWithParent, 0)); - } - - /** - * setup a state where the notification will not be filtered by the - * KeyguardNotificationCoordinator when the keyguard is showing. - */ - private void setupUnfilteredState(NotificationEntry entry) { - // keyguard is showing - when(mKeyguardStateController.isShowing()).thenReturn(true); - - // show notifications on the lockscreen - when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true); - - // neither the current user nor the notification's user is in lockdown - when(mLockscreenUserManager.getCurrentUserId()).thenReturn(CURR_USER_ID); - when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(false); - when(mKeyguardUpdateMonitor.isUserInLockdown(CURR_USER_ID)).thenReturn(false); - - // not in public mode - when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(false); - when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(false); - - // entry's ranking - should show on all lockscreens - // + priority of the notification exceeds the threshold to be shown on the lockscreen - entry.setRanking(new RankingBuilder() - .setKey(mEntry.getKey()) - .setVisibilityOverride(VISIBILITY_PUBLIC) - .setImportance(IMPORTANCE_HIGH) - .build()); - - // settings allows notifications in public mode - when(mLockscreenUserManager.userAllowsNotificationsInPublic(CURR_USER_ID)).thenReturn(true); - when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID)) - .thenReturn(true); - - // notification doesn't have a summary - - // notification is high priority, so it shouldn't be filtered - when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true); - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java new file mode 100644 index 000000000000..de9ea27e7c13 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.interruption; + +import static android.app.Notification.VISIBILITY_PUBLIC; +import static android.app.Notification.VISIBILITY_SECRET; +import static android.app.NotificationManager.IMPORTANCE_HIGH; +import static android.app.NotificationManager.IMPORTANCE_MIN; + +import static com.android.systemui.statusbar.notification.collection.EntryUtilKt.modifyEntry; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.os.Handler; +import android.os.UserHandle; +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.RankingBuilder; +import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider; +import com.android.systemui.statusbar.notification.collection.GroupEntry; +import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.policy.KeyguardStateController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { + private static final int NOTIF_USER_ID = 0; + private static final int CURR_USER_ID = 1; + + @Mock + private Handler mMainHandler; + @Mock private KeyguardStateController mKeyguardStateController; + @Mock private NotificationLockscreenUserManager mLockscreenUserManager; + @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock private HighPriorityProvider mHighPriorityProvider; + @Mock private SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider; + @Mock private KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; + @Mock private StatusBarStateController mStatusBarStateController; + @Mock private BroadcastDispatcher mBroadcastDispatcher; + + private NotificationEntry mEntry; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + // TODO refactor the test of KeyguardNotificationVisibilityProvider out + mKeyguardNotificationVisibilityProvider = spy(new KeyguardNotificationVisibilityProvider( + mContext, + mMainHandler, + mKeyguardStateController, + mLockscreenUserManager, + mKeyguardUpdateMonitor, + mHighPriorityProvider, + mStatusBarStateController, + mBroadcastDispatcher + )); + + mEntry = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .build(); + } + + @Test + public void unfilteredState() { + // GIVEN an 'unfiltered-keyguard-showing' state + setupUnfilteredState(mEntry); + + // THEN don't filter out the entry + assertFalse(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void keyguardNotShowing() { + // GIVEN the lockscreen isn't showing + setupUnfilteredState(mEntry); + when(mKeyguardStateController.isShowing()).thenReturn(false); + + // THEN don't filter out the entry + assertFalse(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void doNotShowLockscreenNotifications() { + // GIVEN an 'unfiltered-keyguard-showing' state + setupUnfilteredState(mEntry); + + // WHEN we shouldn't show any lockscreen notifications + when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false); + + // THEN filter out the entry + assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void lockdown() { + // GIVEN an 'unfiltered-keyguard-showing' state + setupUnfilteredState(mEntry); + + // WHEN the notification's user is in lockdown: + when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true); + + // THEN filter out the entry + assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void publicMode_settingsDisallow() { + // GIVEN an 'unfiltered-keyguard-showing' state + setupUnfilteredState(mEntry); + + // WHEN the notification's user is in public mode and settings are configured to disallow + // notifications in public mode + when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true); + when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID)) + .thenReturn(false); + + // THEN filter out the entry + assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void publicMode_notifDisallowed() { + // GIVEN an 'unfiltered-keyguard-showing' state + setupUnfilteredState(mEntry); + + // WHEN the notification's user is in public mode and settings are configured to disallow + // notifications in public mode + when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true); + mEntry.setRanking(new RankingBuilder() + .setKey(mEntry.getKey()) + .setVisibilityOverride(VISIBILITY_SECRET).build()); + + // THEN filter out the entry + assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void doesNotExceedThresholdToShow() { + // GIVEN an 'unfiltered-keyguard-showing' state + setupUnfilteredState(mEntry); + + // WHEN the notification doesn't exceed the threshold to show on the lockscreen + mEntry.setRanking(new RankingBuilder() + .setKey(mEntry.getKey()) + .setImportance(IMPORTANCE_MIN) + .build()); + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + + // THEN filter out the entry + assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry)); + } + + @Test + public void summaryExceedsThresholdToShow() { + // GIVEN the notification doesn't exceed the threshold to show on the lockscreen + // but it's part of a group (has a parent) + final NotificationEntry entryWithParent = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .build(); + + final GroupEntry parent = new GroupEntryBuilder() + .setKey("test_group_key") + .setSummary(new NotificationEntryBuilder() + .setImportance(IMPORTANCE_HIGH) + .build()) + .addChild(entryWithParent) + .build(); + + setupUnfilteredState(entryWithParent); + entryWithParent.setRanking(new RankingBuilder() + .setKey(entryWithParent.getKey()) + .setImportance(IMPORTANCE_MIN) + .build()); + + // WHEN its parent does exceed threshold tot show on the lockscreen + when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true); + + // THEN don't filter out the entry + assertFalse(mKeyguardNotificationVisibilityProvider.hideNotification(entryWithParent)); + + // WHEN its parent doesn't exceed threshold to show on lockscreen + when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false); + modifyEntry(parent.getSummary(), builder -> builder + .setImportance(IMPORTANCE_MIN) + .done()); + + // THEN filter out the entry + assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(entryWithParent)); + } + + /** + * setup a state where the notification will not be filtered by the + * KeyguardNotificationCoordinator when the keyguard is showing. + */ + private void setupUnfilteredState(NotificationEntry entry) { + // keyguard is showing + when(mKeyguardStateController.isShowing()).thenReturn(true); + + // show notifications on the lockscreen + when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true); + + // neither the current user nor the notification's user is in lockdown + when(mLockscreenUserManager.getCurrentUserId()).thenReturn(CURR_USER_ID); + when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(false); + when(mKeyguardUpdateMonitor.isUserInLockdown(CURR_USER_ID)).thenReturn(false); + + // not in public mode + when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(false); + when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(false); + + // entry's ranking - should show on all lockscreens + // + priority of the notification exceeds the threshold to be shown on the lockscreen + entry.setRanking(new RankingBuilder() + .setKey(mEntry.getKey()) + .setVisibilityOverride(VISIBILITY_PUBLIC) + .setImportance(IMPORTANCE_HIGH) + .build()); + + // settings allows notifications in public mode + when(mLockscreenUserManager.userAllowsNotificationsInPublic(CURR_USER_ID)).thenReturn(true); + when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID)) + .thenReturn(true); + + // notification doesn't have a summary + + // notification is high priority, so it shouldn't be filtered + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java index 2e1297b8b9f6..8a2dc263cf36 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java @@ -30,6 +30,9 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Notification; @@ -48,6 +51,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; @@ -86,6 +90,10 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { BatteryController mBatteryController; @Mock Handler mMockHandler; + @Mock + NotifPipelineFlags mFlags; + @Mock + KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; private NotificationInterruptStateProviderImpl mNotifInterruptionStateProvider; @@ -104,8 +112,9 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { mStatusBarStateController, mHeadsUpManager, mLogger, - mMockHandler); - + mMockHandler, + mFlags, + mKeyguardNotificationVisibilityProvider); mNotifInterruptionStateProvider.mUseHeadsUp = true; } @@ -194,6 +203,16 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { } @Test + public void testDoNotRunFilterOnNewPipeline() { + when(mFlags.isNewPipelineEnabled()).thenReturn(true); + // WHEN this entry should be filtered out + NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT); + mNotifInterruptionStateProvider.shouldHeadsUp(entry); + verify(mFlags, times(1)).isNewPipelineEnabled(); + verify(mNotificationFilter, times(0)).shouldFilterOut(eq(entry)); + } + + @Test public void testShouldNotHeadsUp_suppressedForGroups() throws RemoteException { // GIVEN state for "heads up when awake" is true ensureStateForHeadsUpWhenAwake(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java index 3810783d4f76..c72f89512230 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java @@ -131,6 +131,7 @@ import com.android.systemui.statusbar.notification.collection.legacy.VisualStabi import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; import com.android.systemui.statusbar.notification.init.NotificationsController; +import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -309,7 +310,9 @@ public class CentralSurfacesTest extends SysuiTestCase { mDreamManager, mAmbientDisplayConfiguration, mNotificationFilter, mStatusBarStateController, mBatteryController, mHeadsUpManager, mock(NotificationInterruptLogger.class), - new Handler(TestableLooper.get(this).getLooper())); + new Handler(TestableLooper.get(this).getLooper()), + mock(NotifPipelineFlags.class), + mock(KeyguardNotificationVisibilityProvider.class)); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class)); @@ -994,9 +997,12 @@ public class CentralSurfacesTest extends SysuiTestCase { BatteryController batteryController, HeadsUpManager headsUpManager, NotificationInterruptLogger logger, - Handler mainHandler) { + Handler mainHandler, + NotifPipelineFlags flags, + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { super(contentResolver, powerManager, dreamManager, ambientDisplayConfiguration, filter, - batteryController, controller, headsUpManager, logger, mainHandler); + batteryController, controller, headsUpManager, logger, mainHandler, + flags, keyguardNotificationVisibilityProvider); mUseHeadsUp = true; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt index d65cc7833a68..83eabb667997 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt @@ -1,12 +1,13 @@ package com.android.systemui.statusbar.phone -import android.annotation.IdRes import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View import android.view.ViewGroup import android.view.WindowInsets import android.view.WindowManagerPolicyConstants +import androidx.annotation.AnyRes +import androidx.annotation.IdRes import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.test.filters.SmallTest @@ -72,8 +73,6 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { private lateinit var taskbarVisibilityCallback: OverviewProxyListener private lateinit var windowInsetsCallback: Consumer<WindowInsets> - private val testableResources = mContext.orCreateTestableResources - @Before fun setup() { MockitoAnnotations.initMocks(this) @@ -105,7 +104,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { windowInsetsCallback = windowInsetsCallbackCaptor.value } - fun overrideResource(@IdRes id: Int, value: Any) { + private fun overrideResource(@AnyRes id: Int, value: Any) { mContext.orCreateTestableResources.addOverride(id, value) } @@ -458,6 +457,26 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { } @Test + fun testSplitShadeLayout_qsFrameHasHorizontalMarginsOfZero() { + enableSplitShade() + controller.updateResources() + assertThat(getConstraintSetLayout(R.id.qs_frame).endMargin).isEqualTo(0) + assertThat(getConstraintSetLayout(R.id.qs_frame).startMargin).isEqualTo(0) + } + + @Test + fun testSinglePaneShadeLayout_qsFrameHasHorizontalMarginsSetToCorrectValue() { + disableSplitShade() + controller.updateResources() + val notificationPanelMarginHorizontal = context.resources + .getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal) + assertThat(getConstraintSetLayout(R.id.qs_frame).endMargin) + .isEqualTo(notificationPanelMarginHorizontal) + assertThat(getConstraintSetLayout(R.id.qs_frame).startMargin) + .isEqualTo(notificationPanelMarginHorizontal) + } + + @Test fun testSinglePaneShadeLayout_isAlignedToParent() { disableSplitShade() controller.updateResources() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt index 91c347fc4685..1caacb89ba10 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -41,6 +41,7 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager @@ -83,6 +84,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var userManager: UserManager @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher + @Mock private lateinit var broadcastSender: BroadcastSender @Mock private lateinit var telephonyListenerManager: TelephonyListenerManager @Mock private lateinit var secureSettings: SecureSettings @Mock private lateinit var falsingManager: FalsingManager @@ -159,6 +161,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { handler, activityStarter, broadcastDispatcher, + broadcastSender, uiEventLogger, falsingManager, telephonyListenerManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index 82880febc7f0..78ee9e8921ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -98,6 +98,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; +import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; @@ -343,7 +344,9 @@ public class BubblesTest extends SysuiTestCase { mock(BatteryController.class), mock(HeadsUpManager.class), mock(NotificationInterruptLogger.class), - mock(Handler.class) + mock(Handler.class), + mock(NotifPipelineFlags.class), + mock(KeyguardNotificationVisibilityProvider.class) ); when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java index cc848bc34217..fafe4b3fdb5f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java @@ -85,6 +85,7 @@ import com.android.systemui.statusbar.notification.collection.legacy.Notificatio import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; +import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; @@ -309,7 +310,9 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { mock(BatteryController.class), mock(HeadsUpManager.class), mock(NotificationInterruptLogger.class), - mock(Handler.class) + mock(Handler.class), + mock(NotifPipelineFlags.class), + mock(KeyguardNotificationVisibilityProvider.class) ); when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true); when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java index e698f1e7c4ce..a7f0dc22e849 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java @@ -23,7 +23,9 @@ import android.os.PowerManager; import android.service.dreams.IDreamManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.NotificationFilter; +import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -42,7 +44,9 @@ public class TestableNotificationInterruptStateProviderImpl BatteryController batteryController, HeadsUpManager headsUpManager, NotificationInterruptLogger logger, - Handler mainHandler) { + Handler mainHandler, + NotifPipelineFlags flags, + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { super(contentResolver, powerManager, dreamManager, @@ -52,7 +56,9 @@ public class TestableNotificationInterruptStateProviderImpl statusBarStateController, headsUpManager, logger, - mainHandler); + mainHandler, + flags, + keyguardNotificationVisibilityProvider); mUseHeadsUp = true; } } diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 7f103144b7fb..5ef1008afad5 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -281,9 +281,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ void onDoubleTapAndHold(int displayId); - void requestImeLocked(AccessibilityServiceConnection connection); + void requestImeLocked(AbstractAccessibilityServiceConnection connection); - void unbindImeLocked(AccessibilityServiceConnection connection); + void unbindImeLocked(AbstractAccessibilityServiceConnection connection); } public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName, @@ -387,7 +387,6 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; mRequestAccessibilityButton = (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; - // TODO(b/218193835): request ime when ime flag is set and clean up when ime flag is unset mRequestImeApis = (info.flags & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0; } @@ -439,6 +438,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ // If the XML manifest had data to configure the service its info // should be already set. In such a case update only the dynamically // configurable properties. + boolean oldRequestIme = mRequestImeApis; AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; if (oldInfo != null) { oldInfo.updateDynamicallyConfigurableProperties(mIPlatformCompat, info); @@ -447,6 +447,11 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ setDynamicallyConfigurableProperties(info); } mSystemSupport.onClientChangeLocked(true); + if (!oldRequestIme && mRequestImeApis) { + mSystemSupport.requestImeLocked(this); + } else if (oldRequestIme && !mRequestImeApis) { + mSystemSupport.unbindImeLocked(this); + } } } finally { Binder.restoreCallingIdentity(identity); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 0ea087d6de0f..249ee16afaae 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -4305,7 +4305,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } @Override - public void requestImeLocked(AccessibilityServiceConnection connection) { + public void requestImeLocked(AbstractAccessibilityServiceConnection connection) { mMainHandler.sendMessage(obtainMessage( AccessibilityManagerService::createSessionForConnection, this, connection)); mMainHandler.sendMessage(obtainMessage( @@ -4313,12 +4313,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } @Override - public void unbindImeLocked(AccessibilityServiceConnection connection) { + public void unbindImeLocked(AbstractAccessibilityServiceConnection connection) { mMainHandler.sendMessage(obtainMessage( AccessibilityManagerService::unbindInputForConnection, this, connection)); } - private void createSessionForConnection(AccessibilityServiceConnection connection) { + private void createSessionForConnection(AbstractAccessibilityServiceConnection connection) { synchronized (mLock) { if (mInputSessionRequested) { connection.createImeSessionLocked(); @@ -4326,7 +4326,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private void bindAndStartInputForConnection(AccessibilityServiceConnection connection) { + private void bindAndStartInputForConnection(AbstractAccessibilityServiceConnection connection) { synchronized (mLock) { if (mInputBinding != null) { connection.bindInputLocked(mInputBinding); @@ -4336,7 +4336,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private void unbindInputForConnection(AccessibilityServiceConnection connection) { + private void unbindInputForConnection(AbstractAccessibilityServiceConnection connection) { InputMethodManagerInternal.get().unbindAccessibilityFromCurrentClient(connection.mId); synchronized (mLock) { connection.unbindInputLocked(); diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 2068e6d380b7..68cd28809fd0 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -48,7 +48,6 @@ import com.android.server.pm.PackageSetting; import com.android.server.pm.dex.DynamicCodeLogger; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.AndroidPackageApi; -import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.SharedUserApi; import com.android.server.pm.pkg.component.ParsedMainComponent; @@ -690,8 +689,6 @@ public abstract class PackageManagerInternal { @Nullable public abstract PackageStateInternal getPackageStateInternal(@NonNull String packageName); - public abstract @Nullable PackageState getPackageState(@NonNull String packageName); - @NonNull public abstract ArrayMap<String, ? extends PackageStateInternal> getPackageStates(); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 40ab0c07d166..58fa9fb28a78 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -2013,10 +2013,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return; } - ApnSetting apnSetting = preciseState.getApnSetting(); - synchronized (mRecords) { - if (validatePhoneId(phoneId)) { + if (validatePhoneId(phoneId) && preciseState.getApnSetting() != null) { Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(), preciseState.getApnSetting()); PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId) diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 28b807c5d30b..2b61e7fd2752 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -343,6 +343,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runSetStopUserOnSwitch(pw); case "set-bg-abusive-uids": return runSetBgAbusiveUids(pw); + case "list-bg-exemptions-config": + return runListBgExemptionsConfig(pw); default: return handleDefaultCommands(cmd); } @@ -3292,6 +3294,19 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + private int runListBgExemptionsConfig(PrintWriter pw) throws RemoteException { + final ArraySet<String> sysConfigs = mInternal.mAppRestrictionController + .mBgRestrictionExemptioFromSysConfig; + if (sysConfigs != null) { + for (int i = 0, size = sysConfigs.size(); i < size; i++) { + pw.print(sysConfigs.valueAt(i)); + pw.print(' '); + } + pw.println(); + } + return 0; + } + private Resources getResources(PrintWriter pw) throws RemoteException { // system resources does not contain all the device configuration, construct it manually. Configuration config = mInterface.getConfiguration(); diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java index 6e6cb879ae4f..dc8403aea1b3 100644 --- a/services/core/java/com/android/server/am/AppRestrictionController.java +++ b/services/core/java/com/android/server/am/AppRestrictionController.java @@ -182,7 +182,7 @@ public final class AppRestrictionController { /** * Whether or not to show the foreground service manager on tapping notifications. */ - private static final boolean ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER = false; + private static final boolean ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER = true; private final Context mContext; private final HandlerThread mBgHandlerThread; @@ -241,7 +241,7 @@ public final class AppRestrictionController { /** * The pre-config packages that are exempted from the background restrictions. */ - private ArraySet<String> mBgRestrictionExemptioFromSysConfig; + ArraySet<String> mBgRestrictionExemptioFromSysConfig; /** * Lock specifically for bookkeeping around the carrier-privileged app set. @@ -1595,8 +1595,8 @@ public final class AppRestrictionController { cancelRequestBgRestrictedIfNecessary(packageName, uid); final Intent newIntent = new Intent(ACTION_SHOW_FOREGROUND_SERVICE_MANAGER); newIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mContext.sendBroadcastAsUser(newIntent, - UserHandle.of(UserHandle.getUserId(uid))); + // Task manager runs in SystemUI, which is SYSTEM user only. + mContext.sendBroadcastAsUser(newIntent, UserHandle.SYSTEM); break; } } @@ -1670,9 +1670,10 @@ public final class AppRestrictionController { if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER) { final Intent intent = new Intent(ACTION_SHOW_FOREGROUND_SERVICE_MANAGER); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + // Task manager runs in SystemUI, which is SYSTEM user only. pendingIntent = PendingIntent.getBroadcastAsUser(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, - UserHandle.of(UserHandle.getUserId(uid))); + UserHandle.SYSTEM); } else { final Intent intent = new Intent(Settings.ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL); intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null)); @@ -1750,7 +1751,7 @@ public final class AppRestrictionController { SYSTEM_UID, UserHandle.getUserId(uid)); final String title = mContext.getString(titleRes); final String message = mContext.getString(messageRes, - ai != null ? pm.getText(packageName, ai.labelRes, ai) : packageName); + ai != null ? ai.loadLabel(pm) : packageName); final Icon icon = ai != null ? Icon.createWithResource(packageName, ai.icon) : null; postNotification(notificationId, packageName, uid, title, message, icon, pendingIntent, diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index ea63c080cf68..ade44eac4583 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -21,6 +21,9 @@ import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY; import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE; import static android.text.TextUtils.formatSimple; +import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED; +import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__BOOT_COMPLETED; +import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__LOCKED_BOOT_COMPLETED; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_DEFERRAL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT; @@ -29,6 +32,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -51,6 +55,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -64,6 +69,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; +import android.os.UserManager; import android.permission.IPermissionManager; import android.text.TextUtils; import android.util.EventLog; @@ -75,6 +81,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; +import com.android.server.pm.UserManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -250,12 +257,16 @@ public final class BroadcastQueue { public void enqueueParallelBroadcastLocked(BroadcastRecord r) { r.enqueueClockTime = System.currentTimeMillis(); + r.enqueueTime = SystemClock.uptimeMillis(); + r.enqueueRealTime = SystemClock.elapsedRealtime(); mParallelBroadcasts.add(r); enqueueBroadcastHelper(r); } public void enqueueOrderedBroadcastLocked(BroadcastRecord r) { r.enqueueClockTime = System.currentTimeMillis(); + r.enqueueTime = SystemClock.uptimeMillis(); + r.enqueueRealTime = SystemClock.elapsedRealtime(); mDispatcher.enqueueOrderedBroadcastLocked(r); enqueueBroadcastHelper(r); } @@ -1121,6 +1132,7 @@ public final class BroadcastQueue { while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); + r.dispatchRealTime = SystemClock.elapsedRealtime(); r.dispatchClockTime = System.currentTimeMillis(); if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { @@ -1292,6 +1304,7 @@ public final class BroadcastQueue { performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false, r.userId); + logBootCompletedBroadcastCompletionLatencyIfPossible(r); // Set this to null so that the reference // (local and remote) isn't kept in the mBroadcastHistory. r.resultTo = null; @@ -1408,6 +1421,7 @@ public final class BroadcastQueue { r.receiverTime = SystemClock.uptimeMillis(); if (recIdx == 0) { r.dispatchTime = r.receiverTime; + r.dispatchRealTime = SystemClock.elapsedRealtime(); r.dispatchClockTime = System.currentTimeMillis(); if (mLogLatencyMetrics) { @@ -1866,6 +1880,59 @@ public final class BroadcastQueue { return null; } + private void logBootCompletedBroadcastCompletionLatencyIfPossible(BroadcastRecord r) { + // Only log after last receiver. + // In case of split BOOT_COMPLETED broadcast, make sure only call this method on the + // last BroadcastRecord of the split broadcast which has non-null resultTo. + final int numReceivers = (r.receivers != null) ? r.receivers.size() : 0; + if (r.nextReceiver < numReceivers) { + return; + } + final String action = r.intent.getAction(); + int event = 0; + if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action)) { + event = BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__LOCKED_BOOT_COMPLETED; + } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { + event = BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__BOOT_COMPLETED; + } + if (event != 0) { + final int dispatchLatency = (int)(r.dispatchTime - r.enqueueTime); + final int completeLatency = (int) + (SystemClock.uptimeMillis() - r.enqueueTime); + final int dispatchRealLatency = (int)(r.dispatchRealTime - r.enqueueRealTime); + final int completeRealLatency = (int) + (SystemClock.elapsedRealtime() - r.enqueueRealTime); + int userType = FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN; + // This method is called very infrequently, no performance issue we call + // LocalServices.getService() here. + final UserManagerInternal umInternal = LocalServices.getService( + UserManagerInternal.class); + final UserInfo userInfo = umInternal.getUserInfo(r.userId); + if (userInfo != null) { + userType = UserManager.getUserTypeForStatsd(userInfo.userType); + } + Slog.i(TAG_BROADCAST, + "BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED action:" + + action + + " dispatchLatency:" + dispatchLatency + + " completeLatency:" + completeLatency + + " dispatchRealLatency:" + dispatchRealLatency + + " completeRealLatency:" + completeRealLatency + + " receiversSize:" + r.receivers.size() + + " userId:" + r.userId + + " userType:" + (userInfo != null? userInfo.userType : null)); + FrameworkStatsLog.write( + BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED, + event, + dispatchLatency, + completeLatency, + dispatchRealLatency, + completeRealLatency, + r.userId, + userType); + } + } + private void maybeReportBroadcastDispatchedEventLocked(BroadcastRecord r, int targetUid) { // STOPSHIP (217251579): Temporarily use temp-allowlist reason to identify // push messages and record response events. diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 8b1e829ad836..2ee32b6abe96 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -84,11 +84,14 @@ final class BroadcastRecord extends Binder { boolean deferred; int splitCount; // refcount for result callback, when split int splitToken; // identifier for cross-BroadcastRecord refcount + long enqueueTime; // uptimeMillis when the broadcast was enqueued + long enqueueRealTime; // elapsedRealtime when the broadcast was enqueued long enqueueClockTime; // the clock time the broadcast was enqueued long dispatchTime; // when dispatch started on this set of receivers + long dispatchRealTime; // elapsedRealtime when the broadcast was dispatched long dispatchClockTime; // the clock time the dispatch started long receiverTime; // when current receiver started for timeouts. - long finishTime; // when we finished the broadcast. + long finishTime; // when we finished the current receiver. boolean timeoutExempt; // true if this broadcast is not subject to receiver timeouts int resultCode; // current result code value. String resultData; // current result data value. @@ -169,7 +172,7 @@ final class BroadcastRecord extends Binder { pw.print(prefix); pw.print("dispatchTime="); TimeUtils.formatDuration(dispatchTime, now, pw); pw.print(" ("); - TimeUtils.formatDuration(dispatchClockTime-enqueueClockTime, pw); + TimeUtils.formatDuration(dispatchTime - enqueueTime, pw); pw.print(" since enq)"); if (finishTime != 0) { pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw); @@ -324,8 +327,11 @@ final class BroadcastRecord extends Binder { delivery = from.delivery; duration = from.duration; resultTo = from.resultTo; + enqueueTime = from.enqueueTime; + enqueueRealTime = from.enqueueRealTime; enqueueClockTime = from.enqueueClockTime; dispatchTime = from.dispatchTime; + dispatchRealTime = from.dispatchRealTime; dispatchClockTime = from.dispatchClockTime; receiverTime = from.receiverTime; finishTime = from.finishTime; @@ -378,7 +384,9 @@ final class BroadcastRecord extends Binder { requiredPermissions, excludedPermissions, appOp, options, splitReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId, allowBackgroundActivityStarts, mBackgroundActivityStartsToken, timeoutExempt); - + split.enqueueTime = this.enqueueTime; + split.enqueueRealTime = this.enqueueRealTime; + split.enqueueClockTime = this.enqueueClockTime; split.splitToken = this.splitToken; return split; } @@ -448,9 +456,11 @@ final class BroadcastRecord extends Binder { final BroadcastRecord br = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, excludedPermissions, appOp, options, - uid2receiverList.valueAt(i), resultTo, + uid2receiverList.valueAt(i), null /* _resultTo */, resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId, allowBackgroundActivityStarts, mBackgroundActivityStartsToken, timeoutExempt); + br.enqueueTime = this.enqueueTime; + br.enqueueRealTime = this.enqueueRealTime; br.enqueueClockTime = this.enqueueClockTime; ret.put(uid2receiverList.keyAt(i), br); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index ad176556ba65..879534778800 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -2618,7 +2618,7 @@ class UserController implements Handler.Callback { if (getStartedUserState(userId) == null) { return false; } - if (!mInjector.getUserManager().isCredentialSharedWithParent(userId)) { + if (!mInjector.getUserManager().isCredentialSharableWithParent(userId)) { return false; } if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java index b0a389d8ac68..a76eb8f1e55d 100644 --- a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java +++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java @@ -18,6 +18,7 @@ package com.android.server.app; import android.annotation.NonNull; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; import android.app.ActivityTaskManager; import android.content.Context; import android.content.Intent; @@ -52,6 +53,7 @@ final class GameServiceProviderInstanceFactoryImpl implements GameServiceProvide mContext, new GameClassifierImpl(mContext.getPackageManager()), ActivityManager.getService(), + LocalServices.getService(ActivityManagerInternal.class), ActivityTaskManager.getService(), (WindowManagerService) ServiceManager.getService(Context.WINDOW_SERVICE), LocalServices.getService(WindowManagerInternal.class), diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java index faf5c3826964..e9205230a4ad 100644 --- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java +++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java @@ -21,9 +21,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityManager.RunningTaskInfo; +import android.app.ActivityManagerInternal; import android.app.ActivityTaskManager; import android.app.IActivityManager; import android.app.IActivityTaskManager; +import android.app.IProcessObserver; import android.app.TaskStackListener; import android.content.ComponentName; import android.content.Context; @@ -45,6 +47,7 @@ import android.service.games.IGameServiceController; import android.service.games.IGameSession; import android.service.games.IGameSessionController; import android.service.games.IGameSessionService; +import android.text.TextUtils; import android.util.Slog; import android.view.SurfaceControl; import android.view.SurfaceControlViewHost.SurfacePackage; @@ -143,12 +146,42 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan GameServiceProviderInstanceImpl.this.onTaskFocusChanged(taskId, focused); }); } + }; + + /** + * The TaskStackListener declared above gives us good visibility into game task lifecycle. + * However, it is possible for the Android system to kill all the processes associated with a + * game task (e.g., when the system is under memory pressure or reaches a background process + * limit). When this happens, the game task remains (and no TaskStackListener callbacks are + * invoked), but we would nonetheless want to destroy a game session associated with the task + * if this were to happen. + * + * This process observer gives us visibility into process lifecycles and lets us track all the + * processes associated with each package so that any game sessions associated with the package + * are destroyed if the process count for a given package reaches zero (most packages will + * have at most one task). If processes for a given package are started up again, the destroyed + * game sessions will be re-created. + */ + private final IProcessObserver mProcessObserver = new IProcessObserver.Stub() { + @Override + public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) { + // This callback is used to track how many processes are running for a given package. + // Then, when a process dies, we will know if it was the only process running for that + // package and the associated game sessions should be destroyed. + mBackgroundExecutor.execute(() -> { + GameServiceProviderInstanceImpl.this.onForegroundActivitiesChanged(pid); + }); + } + + @Override + public void onProcessDied(int pid, int uid) { + mBackgroundExecutor.execute(() -> { + GameServiceProviderInstanceImpl.this.onProcessDied(pid); + }); + } - // TODO(b/204503192): Limit the lifespan of the game session in the Game Service provider - // to only when the associated task is running. Right now it is possible for a task to - // move into the background and for all associated processes to die and for the Game Session - // provider's GameSessionService to continue to be running. Ideally we could unbind the - // service when this happens. + @Override + public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {} }; private final IGameServiceController mGameServiceController = @@ -192,6 +225,7 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan private final Context mContext; private final GameClassifier mGameClassifier; private final IActivityManager mActivityManager; + private final ActivityManagerInternal mActivityManagerInternal; private final IActivityTaskManager mActivityTaskManager; private final WindowManagerService mWindowManagerService; private final WindowManagerInternal mWindowManagerInternal; @@ -203,6 +237,12 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan private final ConcurrentHashMap<Integer, GameSessionRecord> mGameSessions = new ConcurrentHashMap<>(); @GuardedBy("mLock") + private final ConcurrentHashMap<Integer, String> mPidToPackageMap = new ConcurrentHashMap<>(); + @GuardedBy("mLock") + private final ConcurrentHashMap<String, Integer> mPackageNameToProcessCountMap = + new ConcurrentHashMap<>(); + + @GuardedBy("mLock") private volatile boolean mIsRunning; GameServiceProviderInstanceImpl( @@ -211,6 +251,7 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan @NonNull Context context, @NonNull GameClassifier gameClassifier, @NonNull IActivityManager activityManager, + @NonNull ActivityManagerInternal activityManagerInternal, @NonNull IActivityTaskManager activityTaskManager, @NonNull WindowManagerService windowManagerService, @NonNull WindowManagerInternal windowManagerInternal, @@ -222,6 +263,7 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan mContext = context; mGameClassifier = gameClassifier; mActivityManager = activityManager; + mActivityManagerInternal = activityManagerInternal; mActivityTaskManager = activityTaskManager; mWindowManagerService = windowManagerService; mWindowManagerInternal = windowManagerInternal; @@ -263,6 +305,12 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan Slog.w(TAG, "Failed to register task stack listener", e); } + try { + mActivityManager.registerProcessObserver(mProcessObserver); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to register process observer", e); + } + mWindowManagerInternal.registerTaskSystemBarsListener(mTaskSystemBarsVisibilityListener); } @@ -274,6 +322,12 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan mIsRunning = false; try { + mActivityManager.unregisterProcessObserver(mProcessObserver); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to unregister process observer", e); + } + + try { mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); } catch (RemoteException e) { Slog.w(TAG, "Failed to unregister task stack listener", e); @@ -596,6 +650,126 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } } + private void onForegroundActivitiesChanged(int pid) { + synchronized (mLock) { + onForegroundActivitiesChangedLocked(pid); + } + } + + @GuardedBy("mLock") + private void onForegroundActivitiesChangedLocked(int pid) { + if (mPidToPackageMap.containsKey(pid)) { + // We are already tracking this pid, nothing to do. + return; + } + + final String packageName = mActivityManagerInternal.getPackageNameByPid(pid); + if (TextUtils.isEmpty(packageName)) { + // Game processes should always have a package name. + return; + } + + if (!gameSessionExistsForPackageNameLocked(packageName)) { + // We only need to track processes for tasks with game session records. + return; + } + + mPidToPackageMap.put(pid, packageName); + final int processCountForPackage = mPackageNameToProcessCountMap.getOrDefault(packageName, + 0) + 1; + mPackageNameToProcessCountMap.put(packageName, processCountForPackage); + + if (DEBUG) { + Slog.d(TAG, "onForegroundActivitiesChangedLocked: tracking pid " + pid + ", for " + + packageName + ". Process count for package: " + processCountForPackage); + } + + // If there are processes for the package, we may need to re-create game sessions + // that are associated with the package + if (processCountForPackage > 0) { + recreateEndedGameSessionsLocked(packageName); + } + } + + @GuardedBy("mLock") + private void recreateEndedGameSessionsLocked(String packageName) { + for (GameSessionRecord gameSessionRecord : mGameSessions.values()) { + if (gameSessionRecord.isGameSessionEndedForProcessDeath() && packageName.equals( + gameSessionRecord.getComponentName().getPackageName())) { + if (DEBUG) { + Slog.d(TAG, + "recreateGameSessionsLocked(): re-creating game session for: " + + packageName + " with taskId: " + + gameSessionRecord.getTaskId()); + } + + final int taskId = gameSessionRecord.getTaskId(); + mGameSessions.put(taskId, GameSessionRecord.awaitingGameSessionRequest(taskId, + gameSessionRecord.getComponentName())); + createGameSessionLocked(gameSessionRecord.getTaskId()); + } + } + } + + private void onProcessDied(int pid) { + synchronized (mLock) { + onProcessDiedLocked(pid); + } + } + + @GuardedBy("mLock") + private void onProcessDiedLocked(int pid) { + final String packageName = mPidToPackageMap.remove(pid); + if (packageName == null) { + // We weren't tracking this process. + return; + } + + final Integer oldProcessCountForPackage = mPackageNameToProcessCountMap.get(packageName); + if (oldProcessCountForPackage == null) { + // This should never happen; we should have a process count for all tracked packages. + Slog.w(TAG, "onProcessDiedLocked(): Missing process count for package"); + return; + } + + final int processCountForPackage = oldProcessCountForPackage - 1; + mPackageNameToProcessCountMap.put(packageName, processCountForPackage); + + // If there are no more processes for the game, then we will terminate any game sessions + // running for the package. + if (processCountForPackage <= 0) { + endGameSessionsForPackageLocked(packageName); + } + } + + @GuardedBy("mLock") + private void endGameSessionsForPackageLocked(String packageName) { + for (GameSessionRecord gameSessionRecord : mGameSessions.values()) { + if (gameSessionRecord.getGameSession() != null && packageName.equals( + gameSessionRecord.getComponentName().getPackageName())) { + if (DEBUG) { + Slog.d(TAG, "endGameSessionsForPackageLocked(): No more processes for " + + packageName + ", ending game session with taskId: " + + gameSessionRecord.getTaskId()); + } + mGameSessions.put(gameSessionRecord.getTaskId(), + gameSessionRecord.withGameSessionEndedOnProcessDeath()); + destroyGameSessionFromRecordLocked(gameSessionRecord); + } + } + } + + @GuardedBy("mLock") + private boolean gameSessionExistsForPackageNameLocked(String packageName) { + for (GameSessionRecord gameSessionRecord : mGameSessions.values()) { + if (packageName.equals(gameSessionRecord.getComponentName().getPackageName())) { + return true; + } + } + + return false; + } + @Nullable private GameSessionViewHostConfiguration createViewHostConfigurationForTask(int taskId) { RunningTaskInfo runningTaskInfo = getRunningTaskInfoForTask(taskId); diff --git a/services/core/java/com/android/server/app/GameSessionRecord.java b/services/core/java/com/android/server/app/GameSessionRecord.java index a241812f7868..74e538ef5011 100644 --- a/services/core/java/com/android/server/app/GameSessionRecord.java +++ b/services/core/java/com/android/server/app/GameSessionRecord.java @@ -35,6 +35,10 @@ final class GameSessionRecord { // A Game Session is created and attached. // GameSessionRecord.getGameSession() != null. GAME_SESSION_ATTACHED, + // A Game Session did exist for a given game task but was destroyed because the last process + // for the game died. + // GameSessionRecord.getGameSession() == null. + GAME_SESSION_ENDED_PROCESS_DEATH, } private final int mTaskId; @@ -99,6 +103,20 @@ final class GameSessionRecord { } @NonNull + public GameSessionRecord withGameSessionEndedOnProcessDeath() { + return new GameSessionRecord( + mTaskId, + State.GAME_SESSION_ENDED_PROCESS_DEATH, + mRootComponentName, + /* gameSession=*/ null, + /* surfacePackage=*/ null); + } + + public boolean isGameSessionEndedForProcessDeath() { + return mState == State.GAME_SESSION_ENDED_PROCESS_DEATH; + } + + @NonNull public int getTaskId() { return mTaskId; } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 3db11d84cbeb..52834cb5917d 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -373,7 +373,7 @@ public class LockSettingsService extends ILockSettings.Stub { LockscreenCredential profileUserPassword) { if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + profileUserId); // Only for profiles that shares credential with parent - if (!isCredentialSharedWithParent(profileUserId)) { + if (!isCredentialSharableWithParent(profileUserId)) { return; } // Do not tie profile when work challenge is enabled @@ -789,7 +789,7 @@ public class LockSettingsService extends ILockSettings.Stub { private void ensureProfileKeystoreUnlocked(int userId) { final KeyStore ks = KeyStore.getInstance(); if (ks.state(userId) == KeyStore.State.LOCKED - && isCredentialSharedWithParent(userId) + && isCredentialSharableWithParent(userId) && hasUnifiedChallenge(userId)) { Slog.i(TAG, "Profile got unlocked, will unlock its keystore"); // If boot took too long and the password in vold got expired, parent keystore will @@ -810,7 +810,7 @@ public class LockSettingsService extends ILockSettings.Stub { // Hide notification first, as tie managed profile lock takes time hideEncryptionNotification(new UserHandle(userId)); - if (isCredentialSharedWithParent(userId)) { + if (isCredentialSharableWithParent(userId)) { tieProfileLockIfNecessary(userId, LockscreenCredential.createNone()); } @@ -1077,7 +1077,7 @@ public class LockSettingsService extends ILockSettings.Stub { final int userCount = users.size(); for (int i = 0; i < userCount; i++) { UserInfo user = users.get(i); - if (isCredentialSharedWithParent(user.id) + if (isCredentialSharableWithParent(user.id) && !getSeparateProfileChallengeEnabledInternal(user.id)) { success &= SyntheticPasswordCrypto.migrateLockSettingsKey( PROFILE_KEY_NAME_ENCRYPT + user.id); @@ -1471,7 +1471,7 @@ public class LockSettingsService extends ILockSettings.Stub { Thread.currentThread().interrupt(); } - if (isCredentialSharedWithParent(userId)) { + if (isCredentialSharableWithParent(userId)) { if (!hasUnifiedChallenge(userId)) { mBiometricDeferredQueue.processPendingLockoutResets(); } @@ -1480,7 +1480,7 @@ public class LockSettingsService extends ILockSettings.Stub { for (UserInfo profile : mUserManager.getProfiles(userId)) { if (profile.id == userId) continue; - if (!isCredentialSharedWithParent(profile.id)) continue; + if (!isCredentialSharableWithParent(profile.id)) continue; if (hasUnifiedChallenge(profile.id)) { if (mUserManager.isUserRunning(profile.id)) { @@ -1517,7 +1517,7 @@ public class LockSettingsService extends ILockSettings.Stub { } private Map<Integer, LockscreenCredential> getDecryptedPasswordsForAllTiedProfiles(int userId) { - if (isCredentialSharedWithParent(userId)) { + if (isCredentialSharableWithParent(userId)) { return null; } Map<Integer, LockscreenCredential> result = new ArrayMap<>(); @@ -1525,7 +1525,7 @@ public class LockSettingsService extends ILockSettings.Stub { final int size = profiles.size(); for (int i = 0; i < size; i++) { final UserInfo profile = profiles.get(i); - if (!isCredentialSharedWithParent(profile.id)) { + if (!isCredentialSharableWithParent(profile.id)) { continue; } final int profileUserId = profile.id; @@ -1560,7 +1560,7 @@ public class LockSettingsService extends ILockSettings.Stub { */ private void synchronizeUnifiedWorkChallengeForProfiles(int userId, Map<Integer, LockscreenCredential> profilePasswordMap) { - if (isCredentialSharedWithParent(userId)) { + if (isCredentialSharableWithParent(userId)) { return; } final boolean isSecure = isUserSecure(userId); @@ -1569,7 +1569,7 @@ public class LockSettingsService extends ILockSettings.Stub { for (int i = 0; i < size; i++) { final UserInfo profile = profiles.get(i); final int profileUserId = profile.id; - if (isCredentialSharedWithParent(profileUserId)) { + if (isCredentialSharableWithParent(profileUserId)) { if (getSeparateProfileChallengeEnabledInternal(profileUserId)) { continue; } @@ -1596,12 +1596,12 @@ public class LockSettingsService extends ILockSettings.Stub { } private boolean isProfileWithUnifiedLock(int userId) { - return isCredentialSharedWithParent(userId) + return isCredentialSharableWithParent(userId) && !getSeparateProfileChallengeEnabledInternal(userId); } private boolean isProfileWithSeparatedLock(int userId) { - return isCredentialSharedWithParent(userId) + return isCredentialSharableWithParent(userId) && getSeparateProfileChallengeEnabledInternal(userId); } @@ -1719,7 +1719,7 @@ public class LockSettingsService extends ILockSettings.Stub { setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null); notifyPasswordChanged(credential, userId); } - if (isCredentialSharedWithParent(userId)) { + if (isCredentialSharableWithParent(userId)) { // Make sure the profile doesn't get locked straight after setting work challenge. setDeviceUnlockedForUser(userId); } @@ -1734,7 +1734,7 @@ public class LockSettingsService extends ILockSettings.Stub { /** * @param savedCredential if the user is a profile with - * {@link UserManager#isCredentialSharedWithParent()} with unified challenge and + * {@link UserManager#isCredentialSharableWithParent()} with unified challenge and * savedCredential is empty, LSS will try to re-derive the profile password internally. * TODO (b/80170828): Fix this so profile password is always passed in. * @param isLockTiedToParent is {@code true} if {@code userId} is a profile and its new @@ -1910,8 +1910,8 @@ public class LockSettingsService extends ILockSettings.Stub { } } - protected boolean isCredentialSharedWithParent(int userId) { - return getUserManagerFromCache(userId).isCredentialSharedWithParent(); + protected boolean isCredentialSharableWithParent(int userId) { + return getUserManagerFromCache(userId).isCredentialSharableWithParent(); } private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) { @@ -2161,7 +2161,7 @@ public class LockSettingsService extends ILockSettings.Stub { final List<UserInfo> profiles = mUserManager.getProfiles(userId); for (UserInfo pi : profiles) { // Unlock profile which shares credential with parent with unified lock - if (isCredentialSharedWithParent(pi.id) + if (isCredentialSharableWithParent(pi.id) && !getSeparateProfileChallengeEnabledInternal(pi.id) && mStorage.hasChildProfileLock(pi.id)) { try { @@ -2555,7 +2555,7 @@ public class LockSettingsService extends ILockSettings.Stub { mManagedProfilePasswordCache.removePassword(userId); gateKeeperClearSecureUserId(userId); - if (unknownUser || isCredentialSharedWithParent(userId)) { + if (unknownUser || isCredentialSharableWithParent(userId)) { removeKeystoreProfileKey(userId); } // Clean up storage last, this is to ensure that cleanupDataForReusedUserIdIfNecessary() @@ -3275,7 +3275,7 @@ public class LockSettingsService extends ILockSettings.Stub { * Returns a fixed pseudorandom byte string derived from the user's synthetic password. * This is used to salt the password history hash to protect the hash against offline * bruteforcing, since rederiving this value requires a successful authentication. - * If user is a profile with {@link UserManager#isCredentialSharedWithParent()} true and with + * If user is a profile with {@link UserManager#isCredentialSharableWithParent()} true and with * unified challenge, currentCredential is ignored. */ @Override diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java index aa467e782e84..2824585bf5aa 100644 --- a/services/core/java/com/android/server/pm/ApkChecksums.java +++ b/services/core/java/com/android/server/pm/ApkChecksums.java @@ -34,6 +34,7 @@ import android.content.Context; import android.content.pm.ApkChecksum; import android.content.pm.Checksum; import android.content.pm.IOnChecksumsReadyListener; +import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.Signature; import android.content.pm.SigningDetails.SignatureSchemeVersion; @@ -62,6 +63,7 @@ import android.util.apk.VerityBuilder; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.security.VerityUtils; +import com.android.server.LocalServices; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.ByteArrayOutputStream; diff --git a/services/core/java/com/android/server/pm/AppIdSettingMap.java b/services/core/java/com/android/server/pm/AppIdSettingMap.java new file mode 100644 index 000000000000..bbef237507bf --- /dev/null +++ b/services/core/java/com/android/server/pm/AppIdSettingMap.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.os.Process; + +import com.android.server.utils.WatchedSparseArray; + +/** + * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID. + */ +public class AppIdSettingMap extends WatchedSparseArray<SettingBase> { + private int mCurrentMaxAppId; + + @Override + public void put(int key, SettingBase value) { + if (key > mCurrentMaxAppId) { + mCurrentMaxAppId = key; + } + super.put(key, value); + } + + @Override + public AppIdSettingMap snapshot() { + AppIdSettingMap l = new AppIdSettingMap(); + snapshot(l, this); + return l; + } + + /** + * @return the maximum of all the App IDs that have been added to the map. 0 if map is empty. + */ + public int getCurrentMaxAppId() { + return mCurrentMaxAppId; + } + + /** + * @return the next available App ID that has not been added to the map + */ + public int getNextAvailableAppId() { + if (mCurrentMaxAppId == 0) { + // No app id has been added yet + return Process.FIRST_APPLICATION_UID; + } else { + return mCurrentMaxAppId + 1; + } + } +} diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index d117967954d3..7b2dc28a396f 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -52,6 +52,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.function.QuadFunction; import com.android.server.FgThread; +import com.android.server.LocalServices; import com.android.server.compat.CompatChange; import com.android.server.om.OverlayReferenceMapper; import com.android.server.pm.parsing.pkg.AndroidPackage; @@ -486,12 +487,12 @@ public class AppsFilter implements Watchable, Snappable { } /** Builder method for an AppsFilter */ - public static AppsFilter create( - PackageManagerInternal pms, PackageManagerServiceInjector injector) { + public static AppsFilter create(@NonNull PackageManagerServiceInjector injector, + @NonNull PackageManagerInternal pmInt) { final boolean forceSystemAppsQueryable = injector.getContext().getResources() .getBoolean(R.bool.config_forceSystemPackagesQueryable); - final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pms, injector); + final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pmInt, injector); final String[] forcedQueryablePackageNames; if (forceSystemAppsQueryable) { // all system apps already queryable, no need to read and parse individual exceptions @@ -512,7 +513,7 @@ public class AppsFilter implements Watchable, Snappable { }; AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig, forcedQueryablePackageNames, forceSystemAppsQueryable, null, - injector.getBackgroundExecutor(), pms); + injector.getBackgroundExecutor(), pmInt); featureConfig.setAppsFilter(appsFilter); return appsFilter; } diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index ecbb4a9d45a1..9ff4aab83cff 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -19,6 +19,7 @@ package com.android.server.pm; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.job.JobInfo; import android.app.job.JobParameters; @@ -269,7 +270,7 @@ public final class BackgroundDexOptService { PackageManagerService pm = mInjector.getPackageManagerService(); ArraySet<String> packagesToOptimize; if (packageNames == null) { - packagesToOptimize = mDexOptHelper.getOptimizablePackages(); + packagesToOptimize = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer()); } else { packagesToOptimize = new ArraySet<>(packageNames); } @@ -334,7 +335,7 @@ public final class BackgroundDexOptService { return false; } - ArraySet<String> pkgs = mDexOptHelper.getOptimizablePackages(); + ArraySet<String> pkgs = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer()); if (pkgs.isEmpty()) { Slog.i(TAG, "No packages to optimize"); markPostBootUpdateCompleted(params); @@ -556,8 +557,8 @@ public final class BackgroundDexOptService { } /** Gets the size of a package. */ - private long getPackageSize(PackageManagerService pm, String pkg) { - PackageInfo info = pm.snapshotComputer().getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM); + private long getPackageSize(@NonNull Computer snapshot, String pkg) { + PackageInfo info = snapshot.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM); long size = 0; if (info != null && info.applicationInfo != null) { File path = Paths.get(info.applicationInfo.sourceDir).toFile(); @@ -605,8 +606,9 @@ public final class BackgroundDexOptService { Slog.d(TAG, "Should Downgrade " + shouldDowngrade); } if (shouldDowngrade) { + final Computer snapshot = pm.snapshotComputer(); Set<String> unusedPackages = - pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis); + snapshot.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis); if (DEBUG) { Slog.d(TAG, "Unsused Packages " + String.join(",", unusedPackages)); } @@ -618,7 +620,7 @@ public final class BackgroundDexOptService { // Should be aborted by the scheduler. return abortCode; } - @DexOptResult int downgradeResult = downgradePackage(pm, pkg, + @DexOptResult int downgradeResult = downgradePackage(snapshot, pm, pkg, /* isForPrimaryDex= */ true, isPostBootUpdate); if (downgradeResult == PackageDexOptimizer.DEX_OPT_PERFORMED) { updatedPackages.add(pkg); @@ -629,7 +631,7 @@ public final class BackgroundDexOptService { return status; } if (supportSecondaryDex) { - downgradeResult = downgradePackage(pm, pkg, + downgradeResult = downgradePackage(snapshot, pm, pkg, /* isForPrimaryDex= */false, isPostBootUpdate); status = convertPackageDexOptimizerStatusToInternal(downgradeResult); if (status != STATUS_OK) { @@ -696,8 +698,8 @@ public final class BackgroundDexOptService { * @return PackageDexOptimizer.DEX_* */ @DexOptResult - private int downgradePackage(PackageManagerService pm, String pkg, boolean isForPrimaryDex, - boolean isPostBootUpdate) { + private int downgradePackage(@NonNull Computer snapshot, PackageManagerService pm, String pkg, + boolean isForPrimaryDex, boolean isPostBootUpdate) { if (DEBUG) { Slog.d(TAG, "Downgrading " + pkg); } @@ -709,15 +711,15 @@ public final class BackgroundDexOptService { if (!isPostBootUpdate) { dexoptFlags |= DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB; } - long package_size_before = getPackageSize(pm, pkg); + long package_size_before = getPackageSize(snapshot, pkg); int result = PackageDexOptimizer.DEX_OPT_SKIPPED; if (isForPrimaryDex || PLATFORM_PACKAGE_NAME.equals(pkg)) { // This applies for system apps or if packages location is not a directory, i.e. // monolithic install. - if (!pm.canHaveOatDir(pkg)) { + if (!pm.canHaveOatDir(snapshot, pkg)) { // For apps that don't have the oat directory, instead of downgrading, // remove their compiler artifacts from dalvik cache. - pm.deleteOatArtifactsOfPackage(pkg); + pm.deleteOatArtifactsOfPackage(snapshot, pkg); } else { result = performDexOptPrimary(pkg, reason, dexoptFlags); } @@ -726,8 +728,9 @@ public final class BackgroundDexOptService { } if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { + final Computer newSnapshot = pm.snapshotComputer(); FrameworkStatsLog.write(FrameworkStatsLog.APP_DOWNGRADED, pkg, package_size_before, - getPackageSize(pm, pkg), /*aggressive=*/ false); + getPackageSize(newSnapshot, pkg), /*aggressive=*/ false); } return result; } diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index 6103d688e2b1..8e853019de90 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -58,10 +58,6 @@ import com.android.server.utils.WatchedLongSparseArray; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; import java.util.List; import java.util.Set; @@ -92,92 +88,69 @@ import java.util.Set; * and other managers (like PermissionManager) mean deadlock is possible. On the * other hand, not overriding in {@link ComputerLocked} may leave a function walking * unstable data. - * - * To coax developers to consider such issues carefully, all methods in - * {@link Computer} must be annotated with <code>@LiveImplementation(override = - * MANDATORY)</code> or <code>LiveImplementation(locked = NOT_ALLOWED)</code>. A unit - * test verifies the annotation and that the annotation corresponds to the code in - * {@link ComputerEngine} and {@link ComputerLocked}. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public interface Computer extends PackageDataSnapshot { /** - * Every method must be annotated. - */ - @Target({ ElementType.METHOD }) - @Retention(RetentionPolicy.RUNTIME) - @interface LiveImplementation { - // A Computer method must be annotated with one of the following values: - // MANDATORY - the method must be overridden in ComputerEngineLive. The - // format of the override is a call to the super method, wrapped in a - // synchronization block. - // NOT_ALLOWED - the method may not appear in the live computer. It must - // be final in the ComputerEngine. - int MANDATORY = 1; - int NOT_ALLOWED = 2; - int override() default MANDATORY; - String rationale() default ""; - } - - /** * Administrative statistics: record that the snapshot has been used. Every call * to use() increments the usage counter. */ - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) default void use() { } /** * Fetch the snapshot usage counter. * @return The number of times this snapshot was used. */ - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) default int getUsed() { return 0; } - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType, long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent, String resolvedType, long flags, int userId, int callingUid, boolean includeInstantApps); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(Intent intent, String resolvedType, long flags, int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits, String pkgName, String instantAppPkgName); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ActivityInfo getActivityInfo(ComponentName component, long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) + + /** + * Important: The provided filterCallingUid is used exclusively to filter out activities + * that can be seen based on user state. It's typically the original caller uid prior + * to clearing. Because it can only be provided by trusted code, its value can be + * trusted and will be used as-is; unlike userId which will be validated by this method. + */ ActivityInfo getActivityInfoInternal(ComponentName component, long flags, int filterCallingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) AndroidPackage getPackage(String packageName); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) AndroidPackage getPackage(int uid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ApplicationInfo generateApplicationInfoFromSettings(String packageName, long flags, int filterCallingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ApplicationInfo getApplicationInfo(String packageName, long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) + + /** + * Important: The provided filterCallingUid is used exclusively to filter out applications + * that can be seen based on user state. It's typically the original caller uid prior + * to clearing. Because it can only be provided by trusted code, its value can be + * trusted and will be used as-is; unlike userId which will be validated by this method. + */ ApplicationInfo getApplicationInfoInternal(String packageName, long flags, int filterCallingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) + + /** + * Report the 'Home' activity which is currently set as "always use this one". If non is set + * then reports the most likely home activity or null if there are more than one. + */ ComponentName getDefaultHomeActivity(int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent, String resolvedType, long flags, int sourceUserId, int parentUserId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) Intent getHomeIntent(); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent, String resolvedType, int userId); @@ -192,15 +165,11 @@ public interface Computer extends PackageDataSnapshot { * @param intent * @return A filtered list of resolved activities. */ - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos, String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid, boolean resolveForStart, int userId, Intent intent); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) PackageInfo generatePackageInfo(PackageStateInternal ps, long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) PackageInfo getPackageInfo(String packageName, long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) PackageInfo getPackageInfoInternal(String packageName, long versionCode, long flags, int filterCallingUid, int userId); @@ -209,79 +178,69 @@ public interface Computer extends PackageDataSnapshot { * known {@link PackageState} instances without a {@link PackageState#getAndroidPackage()} * will not be represented. */ - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) String[] getAllAvailablePackageNames(); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) PackageStateInternal getPackageStateInternal(String packageName); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) PackageStateInternal getPackageStateInternal(String packageName, int callingUid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) - @Nullable PackageState getPackageStateCopied(@NonNull String packageName); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ParceledListSlice<PackageInfo> getInstalledPackages(long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter, int sourceUserId, int targetUserId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) ServiceInfo getServiceInfo(ComponentName component, long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) SharedLibraryInfo getSharedLibraryInfo(String name, long version); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) String getInstantAppPackageName(int callingUid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) String resolveExternalPackageName(AndroidPackage pkg); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) String resolveInternalPackageName(String packageName, long versionCode); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) String[] getPackagesForUid(int uid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) UserInfo getProfileParent(int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean canViewInstantApps(int callingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid, int userId, long flags); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean isCallerSameApp(String packageName, int uid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean isComponentVisibleToInstantApp(@Nullable ComponentName component); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean isComponentVisibleToInstantApp(@Nullable ComponentName component, @PackageManager.ComponentType int type); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) - boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, int userId, + + /** + * From Android R, camera intents have to match system apps. The only exception to this is if + * the DPC has set the camera persistent preferred activity. This case was introduced + * because it is important that the DPC has the ability to set both system and non-system + * camera persistent preferred activities. + * + * @return {@code true} if the intent is a camera intent and the persistent preferred + * activity was not set by the DPC. + */ + boolean isImplicitImageCaptureIntentAndNotSetByDpc(Intent intent, int userId, String resolvedType, long flags); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean isInstantApp(String packageName, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean isInstantAppInternal(String packageName, @UserIdInt int userId, int callingUid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, @Nullable ComponentName component, @PackageManager.ComponentType int componentType, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) boolean shouldFilterApplication(@NonNull SharedUserSetting sus, int callingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) int checkUidPermission(String permName, int uid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) int getPackageUidInternal(String packageName, long flags, int userId, int callingUid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) long updateFlagsForApplication(long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) long updateFlagsForComponent(long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) long updateFlagsForPackage(long flags, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) + + /** + * Update given flags when being used to request {@link ResolveInfo}. + * <p>Instant apps are resolved specially, depending upon context. Minimally, + * {@code}flags{@code} must have the {@link PackageManager#MATCH_INSTANT} + * flag set. However, this flag is only honoured in three circumstances: + * <ul> + * <li>when called from a system process</li> + * <li>when the caller holds the permission {@code android.permission.ACCESS_INSTANT_APPS}</li> + * <li>when resolution occurs to start an activity with a {@code android.intent.action.VIEW} + * action and a {@code android.intent.category.BROWSABLE} category</li> + * </ul> + */ long updateFlagsForResolve(long flags, int userId, int callingUid, boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) long updateFlagsForResolve(long flags, int userId, int callingUid, boolean wantInstantApps, boolean onlyExposedExplicitly, boolean isImplicitImageCaptureIntentAndNotSetByDpc); @@ -299,117 +258,99 @@ public interface Computer extends PackageDataSnapshot { * @param checkShell whether to prevent shell from access if there's a debugging restriction * @param message the message to log on security exception */ - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId, boolean requireFullPermission, boolean checkShell, String message); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) + + /** + * Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS + * or INTERACT_ACROSS_USERS_FULL permissions, if the {@code userId} is not for the caller. + * + * @param checkShell whether to prevent shell from access if there's a debugging restriction + * @param message the message to log on security exception + */ void enforceCrossUserPermission(int callingUid, @UserIdInt int userId, boolean requireFullPermission, boolean checkShell, String message); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) void enforceCrossUserPermission(int callingUid, @UserIdInt int userId, boolean requireFullPermission, boolean checkShell, boolean requirePermissionWhenSameUser, String message); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) SigningDetails getSigningDetails(@NonNull String packageName); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) SigningDetails getSigningDetails(int uid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) boolean filterAppAccess(String packageName, int callingUid, int userId); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) boolean filterAppAccess(int uid, int callingUid); - @Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY) void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityInternal( Intent intent, String resolvedType, long flags, List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered); - @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED) - ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, long flags, + ResolveInfo findPersistentPreferredActivity(Intent intent, String resolvedType, long flags, List<ResolveInfo> query, boolean debug, int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) PreferredIntentResolver getPreferredActivities(@UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ArrayMap<String, ? extends PackageStateInternal> getPackageStates(); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable String getRenamedPackage(@NonNull String packageName); /** * @return set of packages to notify */ - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ArraySet<String> getNotifyPackagesForReplacedReceived(@NonNull String[] packages); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @PackageManagerService.PackageStartability int getPackageStartability(boolean safeMode, @NonNull String packageName, int callingUid, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isPackageAvailable(String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull String[] currentToCanonicalPackageNames(@NonNull String[] names); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull String[] canonicalToCurrentPackageNames(@NonNull String[] names); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull int[] getPackageGids(@NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getTargetSdkVersion(@NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean activitySupportsIntent(@NonNull ComponentName resolveComponentName, @NonNull ComponentName component, @NonNull Intent intent, String resolvedType); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ActivityInfo getReceiverInfo(@NonNull ComponentName component, @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean canRequestPackageInstalls(@NonNull String packageName, int callingUid, int userId, boolean throwIfPermNotDeclared); - @Computer.LiveImplementation(override = LiveImplementation.NOT_ALLOWED) + /** + * Returns true if the system or user is explicitly preventing an otherwise valid installer to + * complete an install. This includes checks like unknown sources and user restrictions. + */ boolean isInstallDisabledForPackage(@NonNull String packageName, int uid, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo, @PackageManager.PackageInfoFlagsBits long flags, int callingUid, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries( @NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ProviderInfo getProviderInfo(@NonNull ComponentName component, @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable String[] getSystemSharedLibraryNames(); @@ -417,136 +358,103 @@ public interface Computer extends PackageDataSnapshot { * @return the state if the given package has a state and isn't filtered by visibility. * Provides no guarantee that the package is in any usable state. */ - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable PackageStateInternal getPackageStateFiltered(@NonNull String packageName, int callingUid, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int checkSignatures(@NonNull String pkg1, @NonNull String pkg2); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int checkUidSignatures(int uid1, int uid2); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean hasSigningCertificate(@NonNull String packageName, @NonNull byte[] certificate, @PackageManager.CertificateInputType int type); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate, @PackageManager.CertificateInputType int type); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull List<String> getAllPackages(); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable String getNameForUid(int uid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable String[] getNamesForUids(@NonNull int[] uids); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getUidForSharedUser(@NonNull String sharedUserName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getFlagsForUid(int uid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getPrivateFlagsForUid(int uid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isUidPrivileged(int uid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull String[] getAppOpPermissionPackages(@NonNull String permissionName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(@NonNull String[] permissions, @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull List<ApplicationInfo> getInstalledApplications( @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId, int callingUid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ProviderInfo resolveContentProvider(@NonNull String name, @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId, int callingUid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ProviderInfo getGrantImplicitAccessProviderInfo(int recipientUid, @NonNull String visibleAuthority); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) void querySyncProviders(boolean safeMode, @NonNull List<String> outNames, @NonNull List<ProviderInfo> outInfo); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName, int uid, @PackageManager.ComponentInfoFlagsBits long flags, @Nullable String metaDataKey); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable InstrumentationInfo getInstrumentationInfo(@NonNull ComponentName component, int flags); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ParceledListSlice<InstrumentationInfo> queryInstrumentation( @NonNull String targetPackage, int flags); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull List<PackageStateInternal> findSharedNonSystemLibraries( @NonNull PackageStateInternal pkgSetting); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean getApplicationHiddenSettingAsUser(@NonNull String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isPackageSuspendedForUser(@NonNull String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isSuspendingAnyPackages(@NonNull String suspendingPackage, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ParceledListSlice<IntentFilter> getAllIntentFilters(@NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean getBlockUninstallForUser(@NonNull String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable SparseArray<int[]> getBroadcastAllowList(@NonNull String packageName, @UserIdInt int[] userIds, boolean isInstantApp); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable String getInstallerPackageName(@NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable InstallSourceInfo getInstallSourceInfo(@NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @PackageManager.EnabledState int getApplicationEnabledSetting(@NonNull String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @PackageManager.EnabledState int getComponentEnabledSetting(@NonNull ComponentName component, int callingUid, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @PackageManager.EnabledState int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, @UserIdInt int userId); @@ -557,25 +465,19 @@ public interface Computer extends PackageDataSnapshot { * are all effectively enabled for the given component. Or if the component cannot be found, * returns false. */ - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable KeySet getKeySetByAlias(@NonNull String packageName, @NonNull String alias); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable KeySet getSigningKeySet(@NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isPackageSignedByKeySet(@NonNull String packageName, @NonNull KeySet ks); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isPackageSignedByKeySetExactly(@NonNull String packageName, @NonNull KeySet ks); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId); @@ -585,49 +487,37 @@ public interface Computer extends PackageDataSnapshot { * package visibility filtering is enabled on it. If the UID is part of a shared user ID, * return {@code true} if any one application belongs to the shared user ID meets the criteria. */ - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean canQueryPackage(int callingUid, @Nullable String targetPackageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getPackageUid(@NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean canAccessComponent(int callingUid, @NonNull ComponentName component, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean isCallerInstallerOfRecord(@NonNull AndroidPackage pkg, int callingUid); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @PackageManager.InstallReason int getInstallReason(@NonNull String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean canPackageQuery(@NonNull String sourcePackageName, @NonNull String targetPackageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean canForwardTo(@NonNull Intent intent, @Nullable String resolvedType, @UserIdInt int sourceUserId, @UserIdInt int targetUserId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull List<ApplicationInfo> getPersistentApplications(boolean safeMode, int flags); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull SparseArray<String> getAppsWithSharedUserIds(); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull String[] getSharedUserPackagesForPackage(@NonNull String packageName, @UserIdInt int userId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull Set<String> getUnusedPackages(long downgradeTimeThresholdMillis); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable CharSequence getHarmfulAppWarning(@NonNull String packageName, @UserIdInt int userId); @@ -638,55 +528,49 @@ public interface Computer extends PackageDataSnapshot { * * @return The filtered packages */ - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull String[] filterOnlySystemPackages(@Nullable String... pkgNames); // The methods in this block should be removed once SettingBase is interface snapshotted - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull List<AndroidPackage> getPackagesForAppId(int appId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getUidTargetSdkVersion(int uid); /** * @see PackageManagerInternal#getProcessesForUid(int) */ - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ArrayMap<String, ProcessInfo> getProcessesForUid(int uid); // End block - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) boolean getBlockUninstall(@UserIdInt int userId, @NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> getSharedLibraries(); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable Pair<PackageStateInternal, SharedUserApi> getPackageOrSharedUser(int appId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable SharedUserApi getSharedUser(int sharedUserAppIde); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @NonNull ComponentResolverApi getComponentResolver(); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable PackageStateInternal getDisabledSystemPackage(@NonNull String packageName); - @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ResolveInfo getInstantAppInstallerInfo(); + + @NonNull + WatchedArrayMap<String, Integer> getFrozenPackages(); + + @Nullable + ComponentName getInstantAppInstallerComponent(); } diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 0c9855b2385d..06e827a8897f 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -466,7 +466,7 @@ public class ComputerEngine implements Computer { flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart, comp != null || pkgName != null /*onlyExposedExplicitly*/, - isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType, + isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType, flags)); List<ResolveInfo> list = Collections.emptyList(); boolean skipPostResolution = false; @@ -1722,15 +1722,6 @@ public class ComputerEngine implements Computer { return mSettings.getPackage(packageName); } - @Nullable - public PackageState getPackageStateCopied(@NonNull String packageName) { - int callingUid = Binder.getCallingUid(); - packageName = resolveInternalPackageNameInternalLocked( - packageName, PackageManager.VERSION_CODE_HIGHEST, callingUid); - PackageStateInternal pkgSetting = mSettings.getPackage(packageName); - return pkgSetting == null ? null : PackageStateImpl.copy(pkgSetting); - } - public final ParceledListSlice<PackageInfo> getInstalledPackages(long flags, int userId) { final int callingUid = Binder.getCallingUid(); if (getInstantAppPackageName(callingUid) != null) { @@ -2468,7 +2459,7 @@ public class ComputerEngine implements Computer { * @return {@code true} if the intent is a camera intent and the persistent preferred * activity was not set by the DPC. */ - public final boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, + public final boolean isImplicitImageCaptureIntentAndNotSetByDpc(Intent intent, int userId, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags) { return intent.isImplicitImageCaptureIntent() && !isPersistentPreferredActivitySetByDpm( intent, userId, resolvedType, flags); @@ -3228,12 +3219,12 @@ public class ComputerEngine implements Computer { flags = updateFlagsForResolve( flags, userId, callingUid, false /*includeInstantApps*/, - isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, + isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType, flags)); intent = PackageManagerServiceUtils.updateIntentForResolve(intent); // Try to find a matching persistent preferred activity. - result.mPreferredResolveInfo = findPersistentPreferredActivityLP(intent, + result.mPreferredResolveInfo = findPersistentPreferredActivity(intent, resolvedType, flags, query, debug, userId); // If a persistent preferred activity matched, use it. @@ -3444,7 +3435,7 @@ public class ComputerEngine implements Computer { userId, queryMayBeFiltered, callingUid, isDeviceProvisioned); } - public final ResolveInfo findPersistentPreferredActivityLP(Intent intent, + public final ResolveInfo findPersistentPreferredActivity(Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, List<ResolveInfo> query, boolean debug, int userId) { final int n = query.size(); @@ -5418,7 +5409,7 @@ public class ComputerEngine implements Computer { } long flags = updateFlagsForResolve(0, parent.id, callingUid, false /*includeInstantApps*/, - isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, parent.id, + isImplicitImageCaptureIntentAndNotSetByDpc(intent, parent.id, resolvedType, 0)); flags |= PackageManager.MATCH_DEFAULT_ONLY; CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr( @@ -5694,4 +5685,17 @@ public class ComputerEngine implements Computer { public ResolveInfo getInstantAppInstallerInfo() { return mInstantAppInstallerInfo; } + + @NonNull + @Override + public WatchedArrayMap<String, Integer> getFrozenPackages() { + return mFrozenPackages; + } + + @Nullable + @Override + public ComponentName getInstantAppInstallerComponent() { + return mLocalInstantAppInstallerActivity == null + ? null : mLocalInstantAppInstallerActivity.getComponentName(); + } } diff --git a/services/core/java/com/android/server/pm/ComputerLocked.java b/services/core/java/com/android/server/pm/ComputerLocked.java index 5d89c7daeaf5..af196d51331f 100644 --- a/services/core/java/com/android/server/pm/ComputerLocked.java +++ b/services/core/java/com/android/server/pm/ComputerLocked.java @@ -16,62 +16,21 @@ package com.android.server.pm; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.UserIdInt; import android.content.ComponentName; -import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; -import android.content.pm.ComponentInfo; -import android.content.pm.InstallSourceInfo; -import android.content.pm.InstrumentationInfo; -import android.content.pm.KeySet; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ParceledListSlice; -import android.content.pm.ProcessInfo; -import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.pm.SharedLibraryInfo; -import android.content.pm.SigningDetails; -import android.content.pm.VersionedPackage; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Pair; -import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.pm.parsing.pkg.AndroidPackage; -import com.android.server.pm.pkg.PackageState; -import com.android.server.pm.pkg.PackageStateInternal; -import com.android.server.pm.pkg.SharedUserApi; -import com.android.server.pm.resolution.ComponentResolverApi; -import com.android.server.utils.WatchedArrayMap; -import com.android.server.utils.WatchedLongSparseArray; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; /** * This subclass is the external interface to the live computer. Some internal helper - * methods are overridden to fetch live data instead of snapshot data. For each - * Computer interface that is overridden in this class, the override takes the PM lock - * and then delegates to the live computer engine. This is required because there are - * no locks taken in the engine itself. + * methods are overridden to fetch live data instead of snapshot data. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public final class ComputerLocked extends ComputerEngine { - private final Object mLock; ComputerLocked(PackageManagerService.Snapshot args) { super(args); - mLock = mService.mLock; } protected ComponentName resolveComponentName() { @@ -83,814 +42,4 @@ public final class ComputerLocked extends ComputerEngine { protected ApplicationInfo androidApplication() { return mService.getCoreAndroidApplication(); } - - public @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent, - String resolvedType, int flags, int userId, int callingUid, - String instantAppPkgName) { - synchronized (mLock) { - return super.queryIntentServicesInternalBody(intent, resolvedType, flags, userId, - callingUid, instantAppPkgName); - } - } - public @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody( - Intent intent, String resolvedType, long flags, int filterCallingUid, int userId, - boolean resolveForStart, boolean allowDynamicSplits, String pkgName, - String instantAppPkgName) { - synchronized (mLock) { - return super.queryIntentActivitiesInternalBody(intent, resolvedType, flags, - filterCallingUid, userId, resolveForStart, allowDynamicSplits, pkgName, - instantAppPkgName); - } - } - public ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags, - int filterCallingUid, int userId) { - synchronized (mLock) { - return super.getActivityInfoInternalBody(component, flags, filterCallingUid, - userId); - } - } - public AndroidPackage getPackage(String packageName) { - synchronized (mLock) { - return super.getPackage(packageName); - } - } - public AndroidPackage getPackage(int uid) { - synchronized (mLock) { - return super.getPackage(uid); - } - } - public ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags, - int filterCallingUid, int userId) { - synchronized (mLock) { - return super.getApplicationInfoInternalBody(packageName, flags, filterCallingUid, - userId); - } - } - public ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody( - Intent intent, int matchFlags, List<ResolveInfo> candidates, - CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) { - synchronized (mLock) { - return super.filterCandidatesWithDomainPreferredActivitiesLPrBody(intent, - matchFlags, candidates, xpDomainInfo, userId, debug); - } - } - public PackageInfo getPackageInfoInternalBody(String packageName, long versionCode, - int flags, int filterCallingUid, int userId) { - synchronized (mLock) { - return super.getPackageInfoInternalBody(packageName, versionCode, flags, - filterCallingUid, userId); - } - } - - @Override - public String[] getAllAvailablePackageNames() { - synchronized (mLock) { - return super.getAllAvailablePackageNames(); - } - } - - public PackageStateInternal getPackageStateInternal(String packageName, int callingUid) { - synchronized (mLock) { - return super.getPackageStateInternal(packageName, callingUid); - } - } - - @Nullable - public PackageState getPackageStateCopied(@NonNull String packageName) { - synchronized (mLock) { - return super.getPackageStateCopied(packageName); - } - } - - public ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId, - int callingUid) { - synchronized (mLock) { - return super.getInstalledPackagesBody(flags, userId, callingUid); - } - } - public ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId, - int callingUid) { - synchronized (mLock) { - return super.getServiceInfoBody(component, flags, userId, callingUid); - } - } - public String getInstantAppPackageName(int callingUid) { - synchronized (mLock) { - return super.getInstantAppPackageName(callingUid); - } - } - public String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId, - boolean isCallerInstantApp) { - synchronized (mLock) { - return super.getPackagesForUidInternalBody(callingUid, userId, appId, - isCallerInstantApp); - } - } - public boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId, - int callingUid) { - synchronized (mLock) { - return super.isInstantAppInternalBody(packageName, userId, callingUid); - } - } - public boolean isInstantAppResolutionAllowedBody(Intent intent, - List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck, - int flags) { - synchronized (mLock) { - return super.isInstantAppResolutionAllowedBody(intent, resolvedActivities, userId, - skipPackageCheck, flags); - } - } - public int getPackageUidInternal(String packageName, int flags, int userId, - int callingUid) { - synchronized (mLock) { - return super.getPackageUidInternal(packageName, flags, userId, callingUid); - } - } - public SigningDetails getSigningDetails(@NonNull String packageName) { - synchronized (mLock) { - return super.getSigningDetails(packageName); - } - } - public SigningDetails getSigningDetails(int uid) { - synchronized (mLock) { - return super.getSigningDetails(uid); - } - } - public boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) { - synchronized (mLock) { - return super.filterAppAccess(pkg, callingUid, userId); - } - } - public boolean filterAppAccess(String packageName, int callingUid, int userId) { - synchronized (mLock) { - return super.filterAppAccess(packageName, callingUid, userId); - } - } - public boolean filterAppAccess(int uid, int callingUid) { - synchronized (mLock) { - return super.filterAppAccess(uid, callingUid); - } - } - public void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState) { - synchronized (mLock) { - super.dump(type, fd, pw, dumpState); - } - } - public PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityBody( - Intent intent, String resolvedType, int flags, List<ResolveInfo> query, boolean always, - boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered, - int callingUid, boolean isDeviceProvisioned) { - synchronized (mLock) { - return super.findPreferredActivityBody(intent, resolvedType, flags, query, always, - removeMatches, debug, userId, queryMayBeFiltered, callingUid, - isDeviceProvisioned); - } - } - - @Override - public PreferredIntentResolver getPreferredActivities(int userId) { - synchronized (mLock) { - return super.getPreferredActivities(userId); - } - } - - @NonNull - @Override - public ArrayMap<String, ? extends PackageStateInternal> getPackageStates() { - synchronized (mLock) { - return super.getPackageStates(); - } - } - - @Nullable - @Override - public String getRenamedPackage(@NonNull String packageName) { - synchronized (mLock) { - return super.getRenamedPackage(packageName); - } - } - - @NonNull - @Override - public ArraySet<String> getNotifyPackagesForReplacedReceived(@NonNull String[] packages) { - synchronized (mLock) { - return super.getNotifyPackagesForReplacedReceived(packages); - } - } - - @Override - public int getPackageStartability(boolean safeMode, @NonNull String packageName, int callingUid, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getPackageStartability(safeMode, packageName, callingUid, userId); - } - } - - @Override - public boolean isPackageAvailable(String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.isPackageAvailable(packageName, userId); - } - } - - @Override - public String[] currentToCanonicalPackageNames(String[] names) { - synchronized (mLock) { - return super.currentToCanonicalPackageNames(names); - } - } - - @Override - public String[] canonicalToCurrentPackageNames(String[] names) { - synchronized (mLock) { - return super.canonicalToCurrentPackageNames(names); - } - } - - @Override - public int[] getPackageGids(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - synchronized (mLock) { - return super.getPackageGids(packageName, flags, userId); - } - } - - @Override - public int getTargetSdkVersion(@NonNull String packageName) { - synchronized (mLock) { - return super.getTargetSdkVersion(packageName); - } - } - - @Override - public boolean activitySupportsIntent(@NonNull ComponentName resolveComponentName, - @NonNull ComponentName component, @NonNull Intent intent, String resolvedType) { - synchronized (mLock) { - return super.activitySupportsIntent(resolveComponentName, component, intent, - resolvedType); - } - } - - @Nullable - @Override - public ActivityInfo getReceiverInfo(@NonNull ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { - synchronized (mLock) { - return super.getReceiverInfo(component, flags, userId); - } - } - - @Nullable - @Override - public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - synchronized (mLock) { - return super.getSharedLibraries(packageName, flags, userId); - } - } - - @Override - public boolean canRequestPackageInstalls(@NonNull String packageName, int callingUid, - @UserIdInt int userId, boolean throwIfPermNotDeclared) { - synchronized (mLock) { - return super.canRequestPackageInstalls(packageName, callingUid, userId, - throwIfPermNotDeclared); - } - } - - @Override - public List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo, - @PackageManager.PackageInfoFlagsBits long flags, int callingUid, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId); - } - } - - @Nullable - @Override - public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries( - @NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getDeclaredSharedLibraries(packageName, flags, userId); - } - } - - @Nullable - @Override - public ProviderInfo getProviderInfo(@NonNull ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { - synchronized (mLock) { - return super.getProviderInfo(component, flags, userId); - } - } - - @Nullable - @Override - public String[] getSystemSharedLibraryNames() { - synchronized (mLock) { - return super.getSystemSharedLibraryNames(); - } - } - - @Override - public int checkSignatures(@NonNull String pkg1, - @NonNull String pkg2) { - synchronized (mLock) { - return super.checkSignatures(pkg1, pkg2); - } - } - - @Override - public int checkUidSignatures(int uid1, int uid2) { - synchronized (mLock) { - return super.checkUidSignatures(uid1, uid2); - } - } - - @Override - public boolean hasSigningCertificate(@NonNull String packageName, @NonNull byte[] certificate, - int type) { - synchronized (mLock) { - return super.hasSigningCertificate(packageName, certificate, type); - } - } - - @Override - public boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate, int type) { - synchronized (mLock) { - return super.hasUidSigningCertificate(uid, certificate, type); - } - } - - @Override - public List<String> getAllPackages() { - synchronized (mLock) { - return super.getAllPackages(); - } - } - - @Nullable - @Override - public String getNameForUid(int uid) { - synchronized (mLock) { - return super.getNameForUid(uid); - } - } - - @Nullable - @Override - public String[] getNamesForUids(int[] uids) { - synchronized (mLock) { - return super.getNamesForUids(uids); - } - } - - @Override - public int getUidForSharedUser(@NonNull String sharedUserName) { - synchronized (mLock) { - return super.getUidForSharedUser(sharedUserName); - } - } - - @Override - public int getFlagsForUid(int uid) { - synchronized (mLock) { - return super.getFlagsForUid(uid); - } - } - - @Override - public int getPrivateFlagsForUid(int uid) { - synchronized (mLock) { - return super.getPrivateFlagsForUid(uid); - } - } - - @Override - public boolean isUidPrivileged(int uid) { - synchronized (mLock) { - return super.isUidPrivileged(uid); - } - } - - @NonNull - @Override - public String[] getAppOpPermissionPackages(@NonNull String permissionName) { - synchronized (mLock) { - return super.getAppOpPermissionPackages(permissionName); - } - } - - @NonNull - @Override - public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions( - @NonNull String[] permissions, @PackageManager.PackageInfoFlagsBits long flags, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getPackagesHoldingPermissions(permissions, flags, userId); - } - } - - @NonNull - @Override - public List<ApplicationInfo> getInstalledApplications( - @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId, - int callingUid) { - synchronized (mLock) { - return super.getInstalledApplications(flags, userId, callingUid); - } - } - - @Nullable - @Override - public ProviderInfo resolveContentProvider(@NonNull String name, - @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId, - int callingUid) { - synchronized (mLock) { - return super.resolveContentProvider(name, flags, userId, callingUid); - } - } - - @Nullable - @Override - public ProviderInfo getGrantImplicitAccessProviderInfo(int recipientUid, - @NonNull String visibleAuthority) { - synchronized (mLock) { - return super.getGrantImplicitAccessProviderInfo(recipientUid, visibleAuthority); - } - } - - @Override - public void querySyncProviders(boolean safeMode, @NonNull List<String> outNames, - @NonNull List<ProviderInfo> outInfo) { - synchronized (mLock) { - super.querySyncProviders(safeMode, outNames, outInfo); - } - } - - @NonNull - @Override - public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName, - int uid, @PackageManager.ComponentInfoFlagsBits long flags, - @Nullable String metaDataKey) { - synchronized (mLock) { - return super.queryContentProviders(processName, uid, flags, metaDataKey); - } - } - - @Nullable - @Override - public InstrumentationInfo getInstrumentationInfo(@NonNull ComponentName component, int flags) { - synchronized (mLock) { - return super.getInstrumentationInfo(component, flags); - } - } - - @NonNull - @Override - public ParceledListSlice<InstrumentationInfo> queryInstrumentation( - @NonNull String targetPackage, int flags) { - synchronized (mLock) { - return super.queryInstrumentation(targetPackage, flags); - } - } - - @NonNull - @Override - public List<PackageStateInternal> findSharedNonSystemLibraries( - @NonNull PackageStateInternal pkgSetting) { - synchronized (mLock) { - return super.findSharedNonSystemLibraries(pkgSetting); - } - } - - @Override - public boolean getApplicationHiddenSettingAsUser(@NonNull String packageName, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getApplicationHiddenSettingAsUser(packageName, userId); - } - } - - @Override - public boolean isPackageSuspendedForUser(@NonNull String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.isPackageSuspendedForUser(packageName, userId); - } - } - - @Override - public boolean isSuspendingAnyPackages(@NonNull String suspendingPackage, - @UserIdInt int userId) { - synchronized (mLock) { - return super.isSuspendingAnyPackages(suspendingPackage, userId); - } - } - - @NonNull - @Override - public ParceledListSlice<IntentFilter> getAllIntentFilters(@NonNull String packageName) { - synchronized (mLock) { - return super.getAllIntentFilters(packageName); - } - } - - @Override - public boolean getBlockUninstallForUser(@NonNull String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.getBlockUninstallForUser(packageName, userId); - } - } - - @Nullable - @Override - public SparseArray<int[]> getBroadcastAllowList(@NonNull String packageName, - @UserIdInt int[] userIds, boolean isInstantApp) { - synchronized (mLock) { - return super.getBroadcastAllowList(packageName, userIds, isInstantApp); - } - } - - @Nullable - @Override - public String getInstallerPackageName(@NonNull String packageName) { - synchronized (mLock) { - return super.getInstallerPackageName(packageName); - } - } - - @Nullable - @Override - public InstallSourceInfo getInstallSourceInfo(@NonNull String packageName) { - synchronized (mLock) { - return super.getInstallSourceInfo(packageName); - } - } - - @Override - public int getApplicationEnabledSetting(@NonNull String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.getApplicationEnabledSetting(packageName, userId); - } - } - - @Override - public int getComponentEnabledSetting(@NonNull ComponentName component, int callingUid, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getComponentEnabledSetting(component, callingUid, userId); - } - } - - @Override - public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getComponentEnabledSettingInternal(component, callingUid, userId); - } - } - - @Override - public boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo, - @UserIdInt int userId) { - synchronized (mLock) { - return super.isComponentEffectivelyEnabled(componentInfo, userId); - } - } - - @Nullable - @Override - public KeySet getKeySetByAlias(@NonNull String packageName, @NonNull String alias) { - synchronized (mLock) { - return super.getKeySetByAlias(packageName, alias); - } - } - - @Nullable - @Override - public KeySet getSigningKeySet(@NonNull String packageName) { - synchronized (mLock) { - return super.getSigningKeySet(packageName); - } - } - - @Override - public boolean isPackageSignedByKeySet(@NonNull String packageName, @NonNull KeySet ks) { - synchronized (mLock) { - return super.isPackageSignedByKeySet(packageName, ks); - } - } - - @Override - public boolean isPackageSignedByKeySetExactly(@NonNull String packageName, @NonNull KeySet ks) { - synchronized (mLock) { - return super.isPackageSignedByKeySetExactly(packageName, ks); - } - } - - @Nullable - @Override - public int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.getVisibilityAllowList(packageName, userId); - } - } - - @Override - public boolean canQueryPackage(int callingUid, @Nullable String targetPackageName) { - synchronized (mLock) { - return super.canQueryPackage(callingUid, targetPackageName); - } - } - - @Override - public int getPackageUid(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - synchronized (mLock) { - return super.getPackageUid(packageName, flags, userId); - } - } - - @Override - public boolean canAccessComponent(int callingUid, @NonNull ComponentName component, - @UserIdInt int userId) { - synchronized (mLock) { - return super.canAccessComponent(callingUid, component, userId); - } - } - - @Override - public boolean isCallerInstallerOfRecord(@NonNull AndroidPackage pkg, int callingUid) { - synchronized (mLock) { - return super.isCallerInstallerOfRecord(pkg, callingUid); - } - } - - @Override - public int getInstallReason(@NonNull String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.getInstallReason(packageName, userId); - } - } - - @Override - public boolean canPackageQuery(@NonNull String sourcePackageName, - @NonNull String targetPackageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.canPackageQuery(sourcePackageName, targetPackageName, userId); - } - } - - @Override - public boolean canForwardTo(@NonNull Intent intent, @Nullable String resolvedType, - @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { - synchronized (mLock) { - return super.canForwardTo(intent, resolvedType, sourceUserId, targetUserId); - } - } - - @NonNull - @Override - public List<ApplicationInfo> getPersistentApplications(boolean safeMode, int flags) { - synchronized (mLock) { - return super.getPersistentApplications(safeMode, flags); - } - } - - @NonNull - @Override - public SparseArray<String> getAppsWithSharedUserIds() { - synchronized (mLock) { - return super.getAppsWithSharedUserIds(); - } - } - - @NonNull - @Override - public String[] getSharedUserPackagesForPackage(@NonNull String packageName, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getSharedUserPackagesForPackage(packageName, userId); - } - } - - @NonNull - @Override - public Set<String> getUnusedPackages(long downgradeTimeThresholdMillis) { - synchronized (mLock) { - return super.getUnusedPackages(downgradeTimeThresholdMillis); - } - } - - @Nullable - @Override - public CharSequence getHarmfulAppWarning(@NonNull String packageName, @UserIdInt int userId) { - synchronized (mLock) { - return super.getHarmfulAppWarning(packageName, userId); - } - } - - @NonNull - @Override - public String[] filterOnlySystemPackages(@Nullable String... pkgNames) { - synchronized (mLock) { - return super.filterOnlySystemPackages(pkgNames); - } - } - - @NonNull - @Override - public List<AndroidPackage> getPackagesForAppId(int appId) { - synchronized (mLock) { - return super.getPackagesForAppId(appId); - } - } - - @Override - public int getUidTargetSdkVersion(int uid) { - synchronized (mLock) { - return super.getUidTargetSdkVersion(uid); - } - } - - @Nullable - @Override - public ArrayMap<String, ProcessInfo> getProcessesForUid(int uid) { - synchronized (mLock) { - return super.getProcessesForUid(uid); - } - } - - @Override - public PackageStateInternal getPackageStateFiltered(@NonNull String packageName, int callingUid, - @UserIdInt int userId) { - synchronized (mLock) { - return super.getPackageStateFiltered(packageName, callingUid, userId); - } - } - - @Override - public boolean getBlockUninstall(@UserIdInt int userId, @NonNull String packageName) { - synchronized (mLock) { - return super.getBlockUninstall(userId, packageName); - } - } - - @NonNull - @Override - public WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> getSharedLibraries() { - synchronized (mLock) { - return super.getSharedLibraries(); - } - } - - @Nullable - @Override - public Pair<PackageStateInternal, SharedUserApi> getPackageOrSharedUser(int appId) { - synchronized (mLock) { - return super.getPackageOrSharedUser(appId); - } - } - - @Nullable - @Override - public SharedUserApi getSharedUser(int sharedUserAppId) { - synchronized (mLock) { - return super.getSharedUser(sharedUserAppId); - } - } - - @NonNull - @Override - public ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId) { - synchronized (mLock) { - return super.getSharedUserPackages(sharedUserAppId); - } - } - - @NonNull - @Override - public ComponentResolverApi getComponentResolver() { - synchronized (mLock) { - return super.getComponentResolver(); - } - } - - @Nullable - @Override - public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) { - synchronized (mLock) { - return super.getDisabledSystemPackage(packageName); - } - } - - @Nullable - @Override - public ResolveInfo getInstantAppInstallerInfo() { - synchronized (mLock) { - return super.getInstantAppInstallerInfo(); - } - } } diff --git a/services/core/java/com/android/server/pm/ComputerTracker.java b/services/core/java/com/android/server/pm/ComputerTracker.java deleted file mode 100644 index 216ad71b4d5d..000000000000 --- a/services/core/java/com/android/server/pm/ComputerTracker.java +++ /dev/null @@ -1,1327 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.pm; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.UserIdInt; -import android.content.ComponentName; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.ComponentInfo; -import android.content.pm.InstallSourceInfo; -import android.content.pm.InstrumentationInfo; -import android.content.pm.KeySet; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; -import android.content.pm.ParceledListSlice; -import android.content.pm.ProcessInfo; -import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.pm.SharedLibraryInfo; -import android.content.pm.SigningDetails; -import android.content.pm.UserInfo; -import android.content.pm.VersionedPackage; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Pair; -import android.util.SparseArray; - -import com.android.server.pm.parsing.pkg.AndroidPackage; -import com.android.server.pm.pkg.PackageState; -import com.android.server.pm.pkg.PackageStateInternal; -import com.android.server.pm.pkg.SharedUserApi; -import com.android.server.pm.resolution.ComponentResolverApi; -import com.android.server.utils.WatchedArrayMap; -import com.android.server.utils.WatchedLongSparseArray; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * This subclass delegates to methods in a Computer after reference-counting the computer. - */ -public final class ComputerTracker implements Computer { - - // The number of times a thread reused a computer in its stack instead of fetching - // a snapshot computer. - private final AtomicInteger mReusedSnapshot = new AtomicInteger(0); - - private final PackageManagerService mService; - ComputerTracker(PackageManagerService s) { - mService = s; - } - - private ThreadComputer snapshot() { - ThreadComputer current = PackageManagerService.sThreadComputer.get(); - if (current.mRefCount > 0) { - current.acquire(); - mReusedSnapshot.incrementAndGet(); - } else { - current.acquire(mService.snapshotComputer()); - } - return current; - } - - public @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, - int filterCallingUid, int userId, boolean resolveForStart, - boolean allowDynamicSplits) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.queryIntentActivitiesInternal(intent, resolvedType, flags, - privateResolveFlags, filterCallingUid, userId, resolveForStart, - allowDynamicSplits); - } finally { - current.release(); - } - } - public @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.queryIntentActivitiesInternal(intent, resolvedType, flags, - userId); - } finally { - current.release(); - } - } - public @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId, - int callingUid, boolean includeInstantApps) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.queryIntentServicesInternal(intent, resolvedType, flags, - userId, callingUid, includeInstantApps); - } finally { - current.release(); - } - } - public @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody( - Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits, - String pkgName, String instantAppPkgName) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.queryIntentActivitiesInternalBody(intent, resolvedType, - flags, filterCallingUid, userId, resolveForStart, allowDynamicSplits, - pkgName, instantAppPkgName); - } finally { - current.release(); - } - } - public ActivityInfo getActivityInfo(ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getActivityInfo(component, flags, userId); - } finally { - current.release(); - } - } - public ActivityInfo getActivityInfoInternal(ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, - int filterCallingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getActivityInfoInternal(component, flags, filterCallingUid, - userId); - } finally { - current.release(); - } - } - public AndroidPackage getPackage(String packageName) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackage(packageName); - } finally { - current.release(); - } - } - public AndroidPackage getPackage(int uid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackage(uid); - } finally { - current.release(); - } - } - public ApplicationInfo generateApplicationInfoFromSettings(String packageName, - long flags, int filterCallingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.generateApplicationInfoFromSettings(packageName, flags, - filterCallingUid, userId); - } finally { - current.release(); - } - } - public ApplicationInfo getApplicationInfo(String packageName, - @PackageManager.ApplicationInfoFlagsBits long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getApplicationInfo(packageName, flags, userId); - } finally { - current.release(); - } - } - public ApplicationInfo getApplicationInfoInternal(String packageName, - @PackageManager.ApplicationInfoFlagsBits long flags, int filterCallingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getApplicationInfoInternal(packageName, flags, - filterCallingUid, userId); - } finally { - current.release(); - } - } - public ComponentName getDefaultHomeActivity(int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getDefaultHomeActivity(userId); - } finally { - current.release(); - } - } - public ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, - int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getHomeActivitiesAsUser(allHomeCandidates, userId); - } finally { - current.release(); - } - } - public CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int sourceUserId, - int parentUserId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getCrossProfileDomainPreferredLpr(intent, resolvedType, - flags, sourceUserId, parentUserId); - } finally { - current.release(); - } - } - public Intent getHomeIntent() { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getHomeIntent(); - } finally { - current.release(); - } - } - public List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters( - Intent intent, String resolvedType, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getMatchingCrossProfileIntentFilters(intent, resolvedType, - userId); - } finally { - current.release(); - } - } - public List<ResolveInfo> applyPostResolutionFilter( - @NonNull List<ResolveInfo> resolveInfos, - String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid, - boolean resolveForStart, int userId, Intent intent) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.applyPostResolutionFilter(resolveInfos, ephemeralPkgName, - allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent); - } finally { - current.release(); - } - } - public PackageInfo generatePackageInfo(PackageStateInternal ps, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.generatePackageInfo(ps, flags, userId); - } finally { - current.release(); - } - } - public PackageInfo getPackageInfo(String packageName, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackageInfo(packageName, flags, userId); - } finally { - current.release(); - } - } - public PackageInfo getPackageInfoInternal(String packageName, long versionCode, - long flags, int filterCallingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackageInfoInternal(packageName, versionCode, flags, - filterCallingUid, userId); - } finally { - current.release(); - } - } - public PackageStateInternal getPackageStateInternal(String packageName) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackageStateInternal(packageName); - } finally { - current.release(); - } - } - public PackageStateInternal getPackageStateInternal(String packageName, int callingUid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackageStateInternal(packageName, callingUid); - } finally { - current.release(); - } - } - - @Nullable - public PackageState getPackageStateCopied(@NonNull String packageName) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackageStateCopied(packageName); - } finally { - current.release(); - } - } - - public ParceledListSlice<PackageInfo> getInstalledPackages(long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getInstalledPackages(flags, userId); - } finally { - current.release(); - } - } - public ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter, - int sourceUserId, int targetUserId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.createForwardingResolveInfoUnchecked(filter, sourceUserId, - targetUserId); - } finally { - current.release(); - } - } - public ServiceInfo getServiceInfo(ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getServiceInfo(component, flags, userId); - } finally { - current.release(); - } - } - public SharedLibraryInfo getSharedLibraryInfo(String name, long version) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getSharedLibraryInfo(name, version); - } finally { - current.release(); - } - } - public SigningDetails getSigningDetails(@NonNull String packageName) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getSigningDetails(packageName); - } finally { - current.release(); - } - } - public SigningDetails getSigningDetails(int uid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getSigningDetails(uid); - } finally { - current.release(); - } - } - public String getInstantAppPackageName(int callingUid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getInstantAppPackageName(callingUid); - } finally { - current.release(); - } - } - public String resolveExternalPackageName(AndroidPackage pkg) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.resolveExternalPackageName(pkg); - } finally { - current.release(); - } - } - public String resolveInternalPackageName(String packageName, long versionCode) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.resolveInternalPackageName(packageName, versionCode); - } finally { - current.release(); - } - } - public String[] getPackagesForUid(int uid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackagesForUid(uid); - } finally { - current.release(); - } - } - public UserInfo getProfileParent(int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getProfileParent(userId); - } finally { - current.release(); - } - } - public boolean canViewInstantApps(int callingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.canViewInstantApps(callingUid, userId); - } finally { - current.release(); - } - } - public boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.filterAppAccess(pkg, callingUid, userId); - } finally { - current.release(); - } - } - public boolean filterAppAccess(String packageName, int callingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.filterAppAccess(packageName, callingUid, userId); - } finally { - current.release(); - } - } - public boolean filterAppAccess(int uid, int callingUid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.filterAppAccess(uid, callingUid); - } finally { - current.release(); - } - } - public boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid, - int userId, @PackageManager.ComponentInfoFlagsBits long flags) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.filterSharedLibPackage(ps, uid, userId, flags); - } finally { - current.release(); - } - } - public boolean isCallerSameApp(String packageName, int uid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isCallerSameApp(packageName, uid); - } finally { - current.release(); - } - } - public boolean isComponentVisibleToInstantApp(@Nullable ComponentName component) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isComponentVisibleToInstantApp(component); - } finally { - current.release(); - } - } - public boolean isComponentVisibleToInstantApp(@Nullable ComponentName component, - @PackageManager.ComponentType int type) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isComponentVisibleToInstantApp(component, type); - } finally { - current.release(); - } - } - public boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, - int userId, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, - userId, resolvedType, flags); - } finally { - current.release(); - } - } - public boolean isInstantApp(String packageName, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isInstantApp(packageName, userId); - } finally { - current.release(); - } - } - public boolean isInstantAppInternal(String packageName, @UserIdInt int userId, - int callingUid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isInstantAppInternal(packageName, userId, callingUid); - } finally { - current.release(); - } - } - public boolean isSameProfileGroup(@UserIdInt int callerUserId, - @UserIdInt int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.isSameProfileGroup(callerUserId, userId); - } finally { - current.release(); - } - } - public boolean shouldFilterApplication(@NonNull SharedUserSetting sus, - int callingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.shouldFilterApplication(sus, callingUid, userId); - } finally { - current.release(); - } - } - public boolean shouldFilterApplication(@Nullable PackageStateInternal ps, - int callingUid, @Nullable ComponentName component, - @PackageManager.ComponentType int componentType, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.shouldFilterApplication(ps, callingUid, component, - componentType, userId); - } finally { - current.release(); - } - } - public boolean shouldFilterApplication(@Nullable PackageStateInternal ps, - int callingUid, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.shouldFilterApplication(ps, callingUid, userId); - } finally { - current.release(); - } - } - public int checkUidPermission(String permName, int uid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.checkUidPermission(permName, uid); - } finally { - current.release(); - } - } - public int getPackageUidInternal(String packageName, - @PackageManager.PackageInfoFlagsBits long flags, int userId, int callingUid) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.getPackageUidInternal(packageName, flags, userId, - callingUid); - } finally { - current.release(); - } - } - public long updateFlagsForApplication(long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.updateFlagsForApplication(flags, userId); - } finally { - current.release(); - } - } - public long updateFlagsForComponent(long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.updateFlagsForComponent(flags, userId); - } finally { - current.release(); - } - } - public long updateFlagsForPackage(long flags, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.updateFlagsForPackage(flags, userId); - } finally { - current.release(); - } - } - public long updateFlagsForResolve(long flags, int userId, int callingUid, - boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.updateFlagsForResolve(flags, userId, callingUid, - wantInstantApps, isImplicitImageCaptureIntentAndNotSetByDpc); - } finally { - current.release(); - } - } - public long updateFlagsForResolve(long flags, int userId, int callingUid, - boolean wantInstantApps, boolean onlyExposedExplicitly, - boolean isImplicitImageCaptureIntentAndNotSetByDpc) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.updateFlagsForResolve(flags, userId, callingUid, - wantInstantApps, onlyExposedExplicitly, - isImplicitImageCaptureIntentAndNotSetByDpc); - } finally { - current.release(); - } - } - public void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState) { - ThreadComputer current = snapshot(); - try { - current.mComputer.dump(type, fd, pw, dumpState); - } finally { - current.release(); - } - } - public void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId, - boolean requireFullPermission, boolean checkShell, String message) { - ThreadComputer current = snapshot(); - try { - current.mComputer.enforceCrossUserOrProfilePermission(callingUid, userId, - requireFullPermission, checkShell, message); - } finally { - current.release(); - } - } - public void enforceCrossUserPermission(int callingUid, @UserIdInt int userId, - boolean requireFullPermission, boolean checkShell, String message) { - ThreadComputer current = snapshot(); - try { - current.mComputer.enforceCrossUserPermission(callingUid, userId, - requireFullPermission, checkShell, message); - } finally { - current.release(); - } - } - public void enforceCrossUserPermission(int callingUid, @UserIdInt int userId, - boolean requireFullPermission, boolean checkShell, - boolean requirePermissionWhenSameUser, String message) { - ThreadComputer current = snapshot(); - try { - current.mComputer.enforceCrossUserPermission(callingUid, userId, - requireFullPermission, checkShell, requirePermissionWhenSameUser, message); - } finally { - current.release(); - } - } - public PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityInternal( - Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug, - int userId, boolean queryMayBeFiltered) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.findPreferredActivityInternal(intent, resolvedType, flags, - query, always, removeMatches, debug, userId, queryMayBeFiltered); - } finally { - current.release(); - } - } - public ResolveInfo findPersistentPreferredActivityLP(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - List<ResolveInfo> query, boolean debug, int userId) { - ThreadComputer current = snapshot(); - try { - return current.mComputer.findPersistentPreferredActivityLP(intent, resolvedType, - flags, query, debug, userId); - } finally { - current.release(); - } - } - - @Override - public String[] getAllAvailablePackageNames() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getAllAvailablePackageNames(); - } - } - - @Override - public PreferredIntentResolver getPreferredActivities(int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPreferredActivities(userId); - } - } - - @NonNull - @Override - public ArrayMap<String, ? extends PackageStateInternal> getPackageStates() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackageStates(); - } - } - - @Nullable - @Override - public String getRenamedPackage(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getRenamedPackage(packageName); - } - } - - @NonNull - @Override - public ArraySet<String> getNotifyPackagesForReplacedReceived(@NonNull String[] packages) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getNotifyPackagesForReplacedReceived(packages); - } - } - - @Override - public int getPackageStartability(boolean safeMode, @NonNull String packageName, int callingUid, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackageStartability(safeMode, packageName, callingUid, - userId); - } - } - - @Override - public boolean isPackageAvailable(String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isPackageAvailable(packageName, userId); - } - } - - @Override - public String[] currentToCanonicalPackageNames(String[] names) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.currentToCanonicalPackageNames(names); - } - } - - @Override - public String[] canonicalToCurrentPackageNames(String[] names) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.canonicalToCurrentPackageNames(names); - } - } - - @Override - public int[] getPackageGids(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackageGids(packageName, flags, userId); - } - } - - @Override - public int getTargetSdkVersion(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getTargetSdkVersion(packageName); - } - } - - @Override - public boolean activitySupportsIntent(@NonNull ComponentName resolveComponentName, - @NonNull ComponentName component, @NonNull Intent intent, String resolvedType) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.activitySupportsIntent(resolveComponentName, component, intent, - resolvedType); - } - } - - @Nullable - @Override - public ActivityInfo getReceiverInfo(@NonNull ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getReceiverInfo(component, flags, userId); - } - } - - @Nullable - @Override - public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSharedLibraries(packageName, flags, userId); - } - } - - @Override - public boolean canRequestPackageInstalls(@NonNull String packageName, int callingUid, - @UserIdInt int userId, boolean throwIfPermNotDeclared) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.canRequestPackageInstalls(packageName, callingUid, userId, - throwIfPermNotDeclared); - } - } - - @Override - public boolean isInstallDisabledForPackage(@NonNull String packageName, int uid, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isInstallDisabledForPackage(packageName, uid, userId); - } - } - - @Override - public List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo, - @PackageManager.PackageInfoFlagsBits long flags, int callingUid, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackagesUsingSharedLibrary(libInfo, flags, callingUid, - userId); - } - } - - @Nullable - @Override - public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries( - @NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getDeclaredSharedLibraries(packageName, flags, userId); - } - } - - @Nullable - @Override - public ProviderInfo getProviderInfo(@NonNull ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getProviderInfo(component, flags, userId); - } - } - - @Nullable - @Override - public String[] getSystemSharedLibraryNames() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSystemSharedLibraryNames(); - } - } - - @Override - public int checkSignatures(@NonNull String pkg1, - @NonNull String pkg2) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.checkSignatures(pkg1, pkg2); - } - } - - @Override - public int checkUidSignatures(int uid1, int uid2) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.checkUidSignatures(uid1, uid2); - } - } - - @Override - public boolean hasSigningCertificate(@NonNull String packageName, @NonNull byte[] certificate, - int type) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.hasSigningCertificate(packageName, certificate, type); - } - } - - @Override - public boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate, int type) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.hasUidSigningCertificate(uid, certificate, type); - } - } - - @Override - public List<String> getAllPackages() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getAllPackages(); - } - } - - @Nullable - @Override - public String getNameForUid(int uid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getNameForUid(uid); - } - } - - @Nullable - @Override - public String[] getNamesForUids(int[] uids) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getNamesForUids(uids); - } - } - - @Override - public int getUidForSharedUser(@NonNull String sharedUserName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getUidForSharedUser(sharedUserName); - } - } - - @Override - public int getFlagsForUid(int uid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getFlagsForUid(uid); - } - } - - @Override - public int getPrivateFlagsForUid(int uid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPrivateFlagsForUid(uid); - } - } - - @Override - public boolean isUidPrivileged(int uid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isUidPrivileged(uid); - } - } - - @NonNull - @Override - public String[] getAppOpPermissionPackages(@NonNull String permissionName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getAppOpPermissionPackages(permissionName); - } - } - - @NonNull - @Override - public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions( - @NonNull String[] permissions, @PackageManager.PackageInfoFlagsBits long flags, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackagesHoldingPermissions(permissions, flags, userId); - } - } - - @NonNull - @Override - public List<ApplicationInfo> getInstalledApplications( - @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId, - int callingUid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getInstalledApplications(flags, userId, callingUid); - } - } - - @Nullable - @Override - public ProviderInfo resolveContentProvider(@NonNull String name, - @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId, - int callingUid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.resolveContentProvider(name, flags, userId, callingUid); - } - } - - @Nullable - @Override - public ProviderInfo getGrantImplicitAccessProviderInfo(int recipientUid, - @NonNull String visibleAuthority) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getGrantImplicitAccessProviderInfo(recipientUid, - visibleAuthority); - } - } - - @Override - public void querySyncProviders(boolean safeMode, @NonNull List<String> outNames, - @NonNull List<ProviderInfo> outInfo) { - try (ThreadComputer current = snapshot()) { - current.mComputer.querySyncProviders(safeMode, outNames, outInfo); - } - } - - @NonNull - @Override - public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName, - int uid, @PackageManager.ComponentInfoFlagsBits long flags, - @Nullable String metaDataKey) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.queryContentProviders(processName, uid, flags, metaDataKey); - } - } - - @Nullable - @Override - public InstrumentationInfo getInstrumentationInfo(@NonNull ComponentName component, int flags) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getInstrumentationInfo(component, flags); - } - } - - @NonNull - @Override - public ParceledListSlice<InstrumentationInfo> queryInstrumentation( - @NonNull String targetPackage, int flags) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.queryInstrumentation(targetPackage, flags); - } - } - - @NonNull - @Override - public List<PackageStateInternal> findSharedNonSystemLibraries( - @NonNull PackageStateInternal pkgSetting) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.findSharedNonSystemLibraries(pkgSetting); - } - } - - @Override - public boolean getApplicationHiddenSettingAsUser(@NonNull String packageName, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getApplicationHiddenSettingAsUser(packageName, userId); - } - } - - @Override - public boolean isPackageSuspendedForUser(@NonNull String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isPackageSuspendedForUser(packageName, userId); - } - } - - @Override - public boolean isSuspendingAnyPackages(@NonNull String suspendingPackage, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isSuspendingAnyPackages(suspendingPackage, userId); - } - } - - @NonNull - @Override - public ParceledListSlice<IntentFilter> getAllIntentFilters(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getAllIntentFilters(packageName); - } - } - - @Override - public boolean getBlockUninstallForUser(@NonNull String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getBlockUninstallForUser(packageName, userId); - } - } - - @Nullable - @Override - public SparseArray<int[]> getBroadcastAllowList(@NonNull String packageName, - @UserIdInt int[] userIds, boolean isInstantApp) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getBroadcastAllowList(packageName, userIds, isInstantApp); - } - } - - @Nullable - @Override - public String getInstallerPackageName(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getInstallerPackageName(packageName); - } - } - - @Nullable - @Override - public InstallSourceInfo getInstallSourceInfo(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getInstallSourceInfo(packageName); - } - } - - @Override - public int getApplicationEnabledSetting(@NonNull String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getApplicationEnabledSetting(packageName, userId); - } - } - - @Override - public int getComponentEnabledSetting(@NonNull ComponentName component, int callingUid, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getComponentEnabledSetting(component, callingUid, userId); - } - } - - @Override - public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getComponentEnabledSettingInternal( - component, callingUid, userId); - } - } - - @Override - public boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isComponentEffectivelyEnabled(componentInfo, userId); - } - } - - @Nullable - @Override - public KeySet getKeySetByAlias(@NonNull String packageName, @NonNull String alias) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getKeySetByAlias(packageName, alias); - } - } - - @Nullable - @Override - public KeySet getSigningKeySet(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSigningKeySet(packageName); - } - } - - @Override - public boolean isPackageSignedByKeySet(@NonNull String packageName, @NonNull KeySet ks) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isPackageSignedByKeySet(packageName, ks); - } - } - - @Override - public boolean isPackageSignedByKeySetExactly(@NonNull String packageName, @NonNull KeySet ks) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isPackageSignedByKeySetExactly(packageName, ks); - } - } - - @Nullable - @Override - public int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getVisibilityAllowList(packageName, userId); - } - } - - @Override - public boolean canQueryPackage(int callingUid, @Nullable String targetPackageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.canQueryPackage(callingUid, targetPackageName); - } - } - - @Override - public int getPackageUid(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackageUid(packageName, flags, userId); - } - } - - @Override - public boolean canAccessComponent(int callingUid, @NonNull ComponentName component, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.canAccessComponent(callingUid, component, userId); - } - } - - @Override - public boolean isCallerInstallerOfRecord(@NonNull AndroidPackage pkg, int callingUid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.isCallerInstallerOfRecord(pkg, callingUid); - } - } - - @Override - public int getInstallReason(@NonNull String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getInstallReason(packageName, userId); - } - } - - @Override - public boolean canPackageQuery(@NonNull String sourcePackageName, - @NonNull String targetPackageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.canPackageQuery(sourcePackageName, targetPackageName, userId); - } - } - - @Override - public boolean canForwardTo(@NonNull Intent intent, @Nullable String resolvedType, - @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.canForwardTo(intent, resolvedType, sourceUserId, targetUserId); - } - } - - @NonNull - @Override - public List<ApplicationInfo> getPersistentApplications(boolean safeMode, int flags) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPersistentApplications(safeMode, flags); - } - } - - @NonNull - @Override - public SparseArray<String> getAppsWithSharedUserIds() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getAppsWithSharedUserIds(); - } - } - - @NonNull - @Override - public String[] getSharedUserPackagesForPackage(@NonNull String packageName, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSharedUserPackagesForPackage(packageName, userId); - } - } - - @NonNull - @Override - public Set<String> getUnusedPackages(long downgradeTimeThresholdMillis) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getUnusedPackages(downgradeTimeThresholdMillis); - } - } - - @Nullable - @Override - public CharSequence getHarmfulAppWarning(@NonNull String packageName, @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getHarmfulAppWarning(packageName, userId); - } - } - - @NonNull - @Override - public String[] filterOnlySystemPackages(@Nullable String... pkgNames) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.filterOnlySystemPackages(pkgNames); - } - } - - @NonNull - @Override - public List<AndroidPackage> getPackagesForAppId(int appId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackagesForAppId(appId); - } - } - - @Override - public int getUidTargetSdkVersion(int uid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getUidTargetSdkVersion(uid); - } - } - - @Nullable - @Override - public ArrayMap<String, ProcessInfo> getProcessesForUid(int uid) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getProcessesForUid(uid); - } - } - - @Override - public PackageStateInternal getPackageStateFiltered(@NonNull String packageName, int callingUid, - @UserIdInt int userId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackageStateFiltered(packageName, callingUid, userId); - } - } - - @Override - public boolean getBlockUninstall(@UserIdInt int userId, @NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getBlockUninstall(userId, packageName); - } - } - - @NonNull - @Override - public WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> getSharedLibraries() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSharedLibraries(); - } - } - - @Nullable - @Override - public Pair<PackageStateInternal, SharedUserApi> getPackageOrSharedUser(int appId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getPackageOrSharedUser(appId); - } - } - - @Nullable - @Override - public SharedUserApi getSharedUser(int sharedUserAppId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSharedUser(sharedUserAppId); - } - } - - @NonNull - @Override - public ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getSharedUserPackages(sharedUserAppId); - } - } - - @NonNull - @Override - public ComponentResolverApi getComponentResolver() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getComponentResolver(); - } - } - - @Nullable - @Override - public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getDisabledSystemPackage(packageName); - } - } - - @Nullable - @Override - public ResolveInfo getInstantAppInstallerInfo() { - try (ThreadComputer current = snapshot()) { - return current.mComputer.getInstantAppInstallerInfo(); - } - } -} diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index 664c7bb929d7..0e1c1ad4120f 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -147,6 +147,7 @@ final class DeletePackageHelper { final SparseArray<TempUserState> priorUserStates; /** enabled state of the uninstalled application */ synchronized (mPm.mLock) { + final Computer computer = mPm.snapshotComputer(); uninstalledPs = mPm.mSettings.getPackageLPr(packageName); if (uninstalledPs == null) { Slog.w(TAG, "Not removing non-existent package " + packageName); @@ -170,10 +171,10 @@ final class DeletePackageHelper { if (pkg != null) { SharedLibraryInfo libraryInfo = null; if (pkg.getStaticSharedLibName() != null) { - libraryInfo = mPm.getSharedLibraryInfo(pkg.getStaticSharedLibName(), + libraryInfo = computer.getSharedLibraryInfo(pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion()); } else if (pkg.getSdkLibName() != null) { - libraryInfo = mPm.getSharedLibraryInfo(pkg.getSdkLibName(), + libraryInfo = computer.getSharedLibraryInfo(pkg.getSdkLibName(), pkg.getSdkLibVersionMajor()); } @@ -183,7 +184,7 @@ final class DeletePackageHelper { continue; } List<VersionedPackage> libClientPackages = - mPm.getPackagesUsingSharedLibrary(libraryInfo, + computer.getPackagesUsingSharedLibrary(libraryInfo, MATCH_KNOWN_PACKAGES, Process.SYSTEM_UID, currUserId); if (!ArrayUtils.isEmpty(libClientPackages)) { Slog.w(TAG, "Not removing package " + pkg.getManifestPackageName() @@ -454,11 +455,11 @@ final class DeletePackageHelper { if (affectedUserIds == null) { affectedUserIds = mPm.resolveUserIds(userId); } + final Computer snapshot = mPm.snapshotComputer(); for (final int affectedUserId : affectedUserIds) { if (hadSuspendAppsPermission.get(affectedUserId)) { - mPm.unsuspendForSuspendingPackage(mPm.snapshotComputer(), packageName, - affectedUserId); - mPm.removeAllDistractingPackageRestrictions(affectedUserId); + mPm.unsuspendForSuspendingPackage(snapshot, packageName, affectedUserId); + mPm.removeAllDistractingPackageRestrictions(snapshot, affectedUserId); } } @@ -621,7 +622,8 @@ final class DeletePackageHelper { final int callingUid = Binder.getCallingUid(); mPm.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DELETE_PACKAGES, null); - final boolean canViewInstantApps = mPm.canViewInstantApps(callingUid, userId); + final Computer snapshot = mPm.snapshotComputer(); + final boolean canViewInstantApps = snapshot.canViewInstantApps(callingUid, userId); Preconditions.checkNotNull(versionedPackage); Preconditions.checkNotNull(observer); Preconditions.checkArgumentInRange(versionedPackage.getLongVersionCode(), @@ -644,12 +646,13 @@ final class DeletePackageHelper { } // Normalize package name to handle renamed packages and static libs - final String internalPackageName = mPm.resolveInternalPackageName(packageName, versionCode); + final String internalPackageName = + snapshot.resolveInternalPackageName(packageName, versionCode); final int uid = Binder.getCallingUid(); - if (!isOrphaned(internalPackageName) + if (!isOrphaned(snapshot, internalPackageName) && !allowSilentUninstall - && !isCallerAllowedToSilentlyUninstall(uid, internalPackageName)) { + && !isCallerAllowedToSilentlyUninstall(snapshot, uid, internalPackageName)) { mPm.mHandler.post(() -> { try { final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); @@ -680,8 +683,7 @@ final class DeletePackageHelper { return; } - if (!deleteAllUsers && mPm.mIPackageManager - .getBlockUninstallForUser(internalPackageName, userId)) { + if (!deleteAllUsers && snapshot.getBlockUninstallForUser(internalPackageName, userId)) { mPm.mHandler.post(() -> { try { observer.onPackageDeleted(packageName, @@ -756,44 +758,45 @@ final class DeletePackageHelper { }); } - private boolean isOrphaned(String packageName) { - final PackageStateInternal packageState = mPm.getPackageStateInternal(packageName); + private boolean isOrphaned(@NonNull Computer snapshot, String packageName) { + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); return packageState != null && packageState.getInstallSource().isOrphaned; } - private boolean isCallerAllowedToSilentlyUninstall(int callingUid, String pkgName) { + private boolean isCallerAllowedToSilentlyUninstall(@NonNull Computer snapshot, int callingUid, + String pkgName) { if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID || UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { return true; } final int callingUserId = UserHandle.getUserId(callingUid); // If the caller installed the pkgName, then allow it to silently uninstall. - if (callingUid == mPm.mIPackageManager.getPackageUid( - mPm.mIPackageManager.getInstallerPackageName(pkgName), 0, callingUserId)) { + if (callingUid == snapshot.getPackageUid(snapshot.getInstallerPackageName(pkgName), 0, + callingUserId)) { return true; } // Allow package verifier to silently uninstall. - if (mPm.mRequiredVerifierPackage != null && callingUid == mPm.mIPackageManager + if (mPm.mRequiredVerifierPackage != null && callingUid == snapshot .getPackageUid(mPm.mRequiredVerifierPackage, 0, callingUserId)) { return true; } // Allow package uninstaller to silently uninstall. - if (mPm.mRequiredUninstallerPackage != null && callingUid == mPm.mIPackageManager + if (mPm.mRequiredUninstallerPackage != null && callingUid == snapshot .getPackageUid(mPm.mRequiredUninstallerPackage, 0, callingUserId)) { return true; } // Allow storage manager to silently uninstall. - if (mPm.mStorageManagerPackage != null && callingUid == mPm.mIPackageManager.getPackageUid( + if (mPm.mStorageManagerPackage != null && callingUid == snapshot.getPackageUid( mPm.mStorageManagerPackage, 0, callingUserId)) { return true; } // Allow caller having MANAGE_PROFILE_AND_DEVICE_OWNERS permission to silently // uninstall for device owner provisioning. - return mPm.mIPackageManager.checkUidPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS, callingUid) + return snapshot.checkUidPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS, callingUid) == PERMISSION_GRANTED; } @@ -899,8 +902,8 @@ final class DeletePackageHelper { int installedForUsersCount = 0; synchronized (mPm.mLock) { // Normalize package name to handle renamed packages and static libs - final String internalPkgName = mPm.resolveInternalPackageName(packageName, - versionCode); + final String internalPkgName = mPm.snapshotComputer() + .resolveInternalPackageName(packageName, versionCode); final PackageSetting ps = mPm.mSettings.getPackageLPr(internalPkgName); if (ps != null) { int[] installedUsers = ps.queryInstalledUsers(mUserManagerInternal.getUserIds(), diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index 74ea7cc9b4e1..50b2e2321886 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -266,8 +266,9 @@ final class DexOptHelper { return; } + final Computer snapshot = mPm.snapshotComputer(); List<PackageStateInternal> pkgSettings = - getPackagesForDexopt(mPm.getPackageStates().values(), mPm); + getPackagesForDexopt(snapshot.getPackageStates().values(), mPm); List<AndroidPackage> pkgs = new ArrayList<>(pkgSettings.size()); for (int index = 0; index < pkgSettings.size(); index++) { @@ -282,17 +283,19 @@ final class DexOptHelper { final int elapsedTimeSeconds = (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime); + final Computer newSnapshot = mPm.snapshotComputer(); + MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_dexopted", stats[0]); MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_skipped", stats[1]); MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_failed", stats[2]); - MetricsLogger.histogram( - mPm.mContext, "opt_dialog_num_total", getOptimizablePackages().size()); + MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_total", + getOptimizablePackages(newSnapshot).size()); MetricsLogger.histogram(mPm.mContext, "opt_dialog_time_s", elapsedTimeSeconds); } - public ArraySet<String> getOptimizablePackages() { + public ArraySet<String> getOptimizablePackages(@NonNull Computer snapshot) { ArraySet<String> pkgs = new ArraySet<>(); - mPm.forEachPackageState(packageState -> { + mPm.forEachPackageState(snapshot, packageState -> { final AndroidPackage pkg = packageState.getPkg(); if (pkg != null && mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) { pkgs.add(packageState.getPackageName()); @@ -302,10 +305,10 @@ final class DexOptHelper { } /*package*/ boolean performDexOpt(DexoptOptions options) { - if (mPm.getInstantAppPackageName(Binder.getCallingUid()) != null) { + final Computer snapshot = mPm.snapshotComputer(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { return false; - } else if (mPm.mIPackageManager.isInstantApp(options.getPackageName(), - UserHandle.getCallingUserId())) { + } else if (snapshot.isInstantApp(options.getPackageName(), UserHandle.getCallingUserId())) { return false; } @@ -417,10 +420,10 @@ final class DexOptHelper { mPm.getDexManager().getPackageUseInfoOrDefault(p.getPackageName()), options); } - public void forceDexOpt(String packageName) { + public void forceDexOpt(@NonNull Computer snapshot, String packageName) { PackageManagerServiceUtils.enforceSystemOrRoot("forceDexOpt"); - final PackageStateInternal packageState = mPm.getPackageStateInternal(packageName); + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); final AndroidPackage pkg = packageState == null ? null : packageState.getPkg(); if (packageState == null || pkg == null) { throw new IllegalArgumentException("Unknown package: " + packageName); @@ -485,19 +488,21 @@ final class DexOptHelper { ArrayList<PackageStateInternal> sortTemp = new ArrayList<>(remainingPkgSettings.size()); + final Computer snapshot = packageManagerService.snapshotComputer(); + // Give priority to core apps. - applyPackageFilter(pkgSetting -> pkgSetting.getPkg().isCoreApp(), result, + applyPackageFilter(snapshot, pkgSetting -> pkgSetting.getPkg().isCoreApp(), result, remainingPkgSettings, sortTemp, packageManagerService); // Give priority to system apps that listen for pre boot complete. Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM); - applyPackageFilter(pkgSetting -> pkgNames.contains(pkgSetting.getPackageName()), result, + applyPackageFilter(snapshot, pkgSetting -> pkgNames.contains(pkgSetting.getPackageName()), result, remainingPkgSettings, sortTemp, packageManagerService); // Give priority to apps used by other apps. DexManager dexManager = packageManagerService.getDexManager(); - applyPackageFilter(pkgSetting -> + applyPackageFilter(snapshot, pkgSetting -> dexManager.getPackageUseInfoOrDefault(pkgSetting.getPackageName()) .isAnyCodePathUsedByOtherApps(), result, remainingPkgSettings, sortTemp, packageManagerService); @@ -535,7 +540,7 @@ final class DexOptHelper { // No historical info. Take all. remainingPredicate = pkgSetting -> true; } - applyPackageFilter(remainingPredicate, result, remainingPkgSettings, sortTemp, + applyPackageFilter(snapshot, remainingPredicate, result, remainingPkgSettings, sortTemp, packageManagerService); if (debug) { @@ -550,7 +555,7 @@ final class DexOptHelper { // package will be removed from {@code packages} and added to {@code result} with its // dependencies. If usage data is available, the positive packages will be sorted by usage // data (with {@code sortTemp} as temporary storage). - private static void applyPackageFilter( + private static void applyPackageFilter(@NonNull Computer snapshot, Predicate<PackageStateInternal> filter, Collection<PackageStateInternal> result, Collection<PackageStateInternal> packages, @@ -568,8 +573,7 @@ final class DexOptHelper { for (PackageStateInternal pkgSetting : sortTemp) { result.add(pkgSetting); - List<PackageStateInternal> deps = - packageManagerService.findSharedNonSystemLibraries(pkgSetting); + List<PackageStateInternal> deps = snapshot.findSharedNonSystemLibraries(pkgSetting); if (!deps.isEmpty()) { deps.removeAll(result); result.addAll(deps); diff --git a/services/core/java/com/android/server/pm/DomainVerificationConnection.java b/services/core/java/com/android/server/pm/DomainVerificationConnection.java index db8c6dc60b5e..20e4dd8a995b 100644 --- a/services/core/java/com/android/server/pm/DomainVerificationConnection.java +++ b/services/core/java/com/android/server/pm/DomainVerificationConnection.java @@ -21,7 +21,6 @@ import static com.android.server.pm.PackageManagerService.DOMAIN_VERIFICATION; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.content.pm.PackageManagerInternal; import android.os.Binder; import android.os.Message; import android.os.UserHandle; @@ -35,13 +34,10 @@ import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV2; public final class DomainVerificationConnection implements DomainVerificationService.Connection, DomainVerificationProxyV1.Connection, DomainVerificationProxyV2.Connection { final PackageManagerService mPm; - final PackageManagerInternal mPmInternal; final UserManagerInternal mUmInternal; - // TODO(b/198166813): remove PMS dependency DomainVerificationConnection(PackageManagerService pm) { mPm = pm; - mPmInternal = mPm.mInjector.getLocalService(PackageManagerInternal.class); mUmInternal = mPm.mInjector.getLocalService(UserManagerInternal.class); } @@ -82,18 +78,18 @@ public final class DomainVerificationConnection implements DomainVerificationSer @Override public boolean isCallerPackage(int callingUid, @NonNull String packageName) { final int callingUserId = UserHandle.getUserId(callingUid); - return callingUid == mPmInternal.getPackageUid(packageName, 0, callingUserId); + return callingUid == mPm.snapshotComputer().getPackageUid(packageName, 0, callingUserId); } @Nullable @Override public AndroidPackage getPackage(@NonNull String packageName) { - return mPmInternal.getPackage(packageName); + return mPm.snapshotComputer().getPackage(packageName); } @Override public boolean filterAppAccess(String packageName, int callingUid, int userId) { - return mPmInternal.filterAppAccess(packageName, callingUid, userId); + return mPm.snapshotComputer().filterAppAccess(packageName, callingUid, userId); } @Override @@ -108,6 +104,6 @@ public final class DomainVerificationConnection implements DomainVerificationSer @NonNull public Computer snapshot() { - return (Computer) mPmInternal.snapshot(); + return mPm.snapshotComputer(); } } diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java index 05ef3c4ec300..f83ef5aea23a 100644 --- a/services/core/java/com/android/server/pm/DumpHelper.java +++ b/services/core/java/com/android/server/pm/DumpHelper.java @@ -55,6 +55,7 @@ final class DumpHelper { @NeverCompile // Avoid size overhead of debugging code. public void doDump(FileDescriptor fd, PrintWriter pw, String[] args) { + final Computer snapshot = mPm.snapshotComputer(); DumpState dumpState = new DumpState(); ArraySet<String> permissionNames = null; @@ -121,7 +122,7 @@ final class DumpHelper { } // Normalize package name to handle renamed packages and static libs - pkg = mPm.resolveInternalPackageName(pkg, PackageManager.VERSION_CODE_HIGHEST); + pkg = snapshot.resolveInternalPackageName(pkg, PackageManager.VERSION_CODE_HIGHEST); pw.println(mPm.checkPermission(perm, pkg, user)); return; @@ -243,7 +244,7 @@ final class DumpHelper { // Return if the package doesn't exist. if (packageName != null - && mPm.getPackageStateInternal(packageName) == null + && snapshot.getPackageStateInternal(packageName) == null && !mPm.mApexManager.isApexPackage(packageName)) { pw.println("Unable to find package: " + packageName); return; @@ -257,7 +258,7 @@ final class DumpHelper { if (!checkin && dumpState.isDumping(DumpState.DUMP_VERSION) && packageName == null) { - mPm.dumpComputer(DumpState.DUMP_VERSION, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_VERSION, fd, pw, dumpState); } if (!checkin @@ -273,7 +274,7 @@ final class DumpHelper { final String knownPackage = PackageManagerInternal.knownPackageToString(i); ipw.print(knownPackage); ipw.println(":"); - final String[] pkgNames = mPm.getKnownPackageNamesInternal(i, + final String[] pkgNames = mPm.getKnownPackageNamesInternal(snapshot, i, UserHandle.USER_SYSTEM); ipw.increaseIndent(); if (ArrayUtils.isEmpty(pkgNames)) { @@ -288,8 +289,6 @@ final class DumpHelper { ipw.decreaseIndent(); } - final Computer snapshot = mPm.snapshotComputer(); - if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) { final String requiredVerifierPackage = mPm.mRequiredVerifierPackage; @@ -343,7 +342,7 @@ final class DumpHelper { if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) { - mPm.dumpComputer(DumpState.DUMP_LIBS, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_LIBS, fd, pw, dumpState); } if (dumpState.isDumping(DumpState.DUMP_FEATURES) @@ -389,17 +388,17 @@ final class DumpHelper { } if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) { - mPm.dumpComputer(DumpState.DUMP_PREFERRED, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_PREFERRED, fd, pw, dumpState); } if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML) && packageName == null) { - mPm.dumpComputer(DumpState.DUMP_PREFERRED_XML, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_PREFERRED_XML, fd, pw, dumpState); } if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) { - mPm.dumpComputer(DumpState.DUMP_DOMAIN_PREFERRED, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_DOMAIN_PREFERRED, fd, pw, dumpState); } if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) { @@ -429,7 +428,7 @@ final class DumpHelper { if (!checkin && dumpState.isDumping(DumpState.DUMP_QUERIES)) { - mPm.dumpComputer(DumpState.DUMP_QUERIES, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_QUERIES, fd, pw, dumpState); } if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) { @@ -529,12 +528,12 @@ final class DumpHelper { if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) { - mPm.dumpComputer(DumpState.DUMP_DEXOPT, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_DEXOPT, fd, pw, dumpState); } if (!checkin && dumpState.isDumping(DumpState.DUMP_COMPILER_STATS)) { - mPm.dumpComputer(DumpState.DUMP_COMPILER_STATS, fd, pw, dumpState); + snapshot.dump(DumpState.DUMP_COMPILER_STATS, fd, pw, dumpState); } if (dumpState.isDumping(DumpState.DUMP_MESSAGES) @@ -581,7 +580,7 @@ final class DumpHelper { pw.println(" Known digesters list flag: " + PackageManagerService.getKnownDigestersList()); - PerUidReadTimeouts[] items = mPm.getPerUidReadTimeouts(); + PerUidReadTimeouts[] items = mPm.getPerUidReadTimeouts(snapshot); pw.println(" Timeouts (" + items.length + "):"); for (PerUidReadTimeouts item : items) { pw.print(" ("); diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java new file mode 100644 index 000000000000..e1aee6d747f4 --- /dev/null +++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java @@ -0,0 +1,1189 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + + +import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.annotation.UserIdInt; +import android.app.role.RoleManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageDeleteObserver; +import android.content.pm.IPackageDeleteObserver2; +import android.content.pm.IPackageInstaller; +import android.content.pm.IPackageManager; +import android.content.pm.IPackageStatsObserver; +import android.content.pm.InstallSourceInfo; +import android.content.pm.InstrumentationInfo; +import android.content.pm.IntentFilterVerificationInfo; +import android.content.pm.KeySet; +import android.content.pm.ModuleInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.VersionedPackage; +import android.content.pm.dex.IArtManager; +import android.os.Binder; +import android.os.Process; +import android.os.RemoteException; +import android.os.Trace; +import android.os.UserHandle; +import android.permission.PermissionManager; + +import com.android.internal.R; +import com.android.internal.content.InstallLocationUtils; +import com.android.internal.util.CollectionUtils; +import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; +import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1; + +import java.util.List; +import java.util.Objects; + +/** + * Contains all simply proxy methods which need a snapshot instance and just calls a method on it, + * with no additional logic. Separated with all methods marked final and deprecated to prevent their + * use from other methods which may need a snapshot for non-trivial reasons. + */ +public abstract class IPackageManagerBase extends IPackageManager.Stub { + + @NonNull + private final PackageManagerService mService; + + @NonNull + private final Context mContext; + + @NonNull private final DexOptHelper mDexOptHelper; + @NonNull private final ModuleInfoProvider mModuleInfoProvider; + @NonNull private final PreferredActivityHelper mPreferredActivityHelper; + @NonNull private final ResolveIntentHelper mResolveIntentHelper; + + @NonNull + private final DomainVerificationManagerInternal mDomainVerificationManager; + + @NonNull + private final DomainVerificationConnection mDomainVerificationConnection; + + @NonNull + private final PackageInstallerService mInstallerService; + + @NonNull + private final PackageProperty mPackageProperty; + + @NonNull + private final ComponentName mResolveComponentName; + + @Nullable + private final ComponentName mInstantAppResolverSettingsComponent; + + @NonNull + private final String mRequiredSupplementalProcessPackage; + + @Nullable + private final String mServicesExtensionPackageName; + + @Nullable + private final String mSharedSystemSharedLibraryPackageName; + + public IPackageManagerBase(@NonNull PackageManagerService service, @NonNull Context context, + @NonNull DexOptHelper dexOptHelper, @NonNull ModuleInfoProvider moduleInfoProvider, + @NonNull PreferredActivityHelper preferredActivityHelper, + @NonNull ResolveIntentHelper resolveIntentHelper, + @NonNull DomainVerificationManagerInternal domainVerificationManager, + @NonNull DomainVerificationConnection domainVerificationConnection, + @NonNull PackageInstallerService installerService, + @NonNull PackageProperty packageProperty, @NonNull ComponentName resolveComponentName, + @Nullable ComponentName instantAppResolverSettingsComponent, + @NonNull String requiredSupplementalProcessPackage, + @Nullable String servicesExtensionPackageName, + @Nullable String sharedSystemSharedLibraryPackageName) { + mService = service; + mContext = context; + mDexOptHelper = dexOptHelper; + mModuleInfoProvider = moduleInfoProvider; + mPreferredActivityHelper = preferredActivityHelper; + mResolveIntentHelper = resolveIntentHelper; + mDomainVerificationManager = domainVerificationManager; + mDomainVerificationConnection = domainVerificationConnection; + mInstallerService = installerService; + mPackageProperty = packageProperty; + mResolveComponentName = resolveComponentName; + mInstantAppResolverSettingsComponent = instantAppResolverSettingsComponent; + mRequiredSupplementalProcessPackage = requiredSupplementalProcessPackage; + mServicesExtensionPackageName = servicesExtensionPackageName; + mSharedSystemSharedLibraryPackageName = sharedSystemSharedLibraryPackageName; + } + + protected Computer snapshot() { + return mService.snapshotComputer(); + } + + @Override + @Deprecated + public final boolean activitySupportsIntent(ComponentName component, Intent intent, + String resolvedType) { + return snapshot().activitySupportsIntent(mResolveComponentName, component, intent, + resolvedType); + } + + @Override + @Deprecated + public final void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage, + int sourceUserId, int targetUserId, int flags) { + mService.addCrossProfileIntentFilter(snapshot(), + new WatchedIntentFilter(intentFilter), ownerPackage, sourceUserId, targetUserId, + flags); + } + + // NOTE: Can't remove due to unsupported app usage + @Override + @Deprecated + public final boolean addPermission(PermissionInfo info) { + // Because this is accessed via the package manager service AIDL, + // go through the permission manager service AIDL + return mContext.getSystemService(PermissionManager.class).addPermission(info, false); + } + + // NOTE: Can't remove due to unsupported app usage + @Override + @Deprecated + public final boolean addPermissionAsync(PermissionInfo info) { + // Because this is accessed via the package manager service AIDL, + // go through the permission manager service AIDL + return mContext.getSystemService(PermissionManager.class).addPermission(info, true); + } + + @Override + @Deprecated + public final void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity, + int userId) { + mPreferredActivityHelper.addPersistentPreferredActivity(new WatchedIntentFilter(filter), + activity, userId); + } + + @Override + @Deprecated + public final void addPreferredActivity(IntentFilter filter, int match, + ComponentName[] set, ComponentName activity, int userId, boolean removeExisting) { + mPreferredActivityHelper.addPreferredActivity(snapshot(), + new WatchedIntentFilter(filter), match, set, activity, true, userId, + "Adding preferred", removeExisting); + } + + /* + * Returns if intent can be forwarded from the sourceUserId to the targetUserId + */ + @Override + @Deprecated + public final boolean canForwardTo(@NonNull Intent intent, @Nullable String resolvedType, + @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { + return snapshot().canForwardTo(intent, resolvedType, sourceUserId, targetUserId); + } + + @Override + @Deprecated + public final boolean canRequestPackageInstalls(String packageName, int userId) { + return snapshot().canRequestPackageInstalls(packageName, Binder.getCallingUid(), userId, + true /* throwIfPermNotDeclared*/); + } + + @Override + @Deprecated + public final String[] canonicalToCurrentPackageNames(String[] names) { + return snapshot().canonicalToCurrentPackageNames(names); + } + + // NOTE: Can't remove due to unsupported app usage + @Override + @Deprecated + public final int checkPermission(String permName, String pkgName, int userId) { + return mService.checkPermission(permName, pkgName, userId); + } + + @Override + @Deprecated + public final int checkSignatures(@NonNull String pkg1, @NonNull String pkg2) { + return snapshot().checkSignatures(pkg1, pkg2); + } + + @Override + @Deprecated + public final int checkUidPermission(String permName, int uid) { + return snapshot().checkUidPermission(permName, uid); + } + + @Override + @Deprecated + public final int checkUidSignatures(int uid1, int uid2) { + return snapshot().checkUidSignatures(uid1, uid2); + } + + @Override + @Deprecated + public final void clearPackagePersistentPreferredActivities(String packageName, int userId) { + mPreferredActivityHelper.clearPackagePersistentPreferredActivities(packageName, userId); + } + + @Override + @Deprecated + public final void clearPackagePreferredActivities(String packageName) { + mPreferredActivityHelper.clearPackagePreferredActivities(snapshot(), + packageName); + } + + @Override + @Deprecated + public final String[] currentToCanonicalPackageNames(String[] names) { + return snapshot().currentToCanonicalPackageNames(names); + } + + @Override + @Deprecated + public final void deleteExistingPackageAsUser(VersionedPackage versionedPackage, + final IPackageDeleteObserver2 observer, final int userId) { + mService.deleteExistingPackageAsUser(versionedPackage, observer, userId); + } + + @Override + @Deprecated + public final void deletePackageAsUser(String packageName, int versionCode, + IPackageDeleteObserver observer, int userId, int flags) { + deletePackageVersioned(new VersionedPackage(packageName, versionCode), + new PackageManager.LegacyPackageDeleteObserver(observer).getBinder(), userId, + flags); + } + + @Override + @Deprecated + public final void deletePackageVersioned(VersionedPackage versionedPackage, + final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) { + mService.deletePackageVersioned(versionedPackage, observer, userId, deleteFlags); + } + + @Override + @Deprecated + public final ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) { + return mPreferredActivityHelper.findPersistentPreferredActivity(snapshot(), intent, userId); + } + + @Override + @Deprecated + public final void forceDexOpt(String packageName) { + mDexOptHelper.forceDexOpt(snapshot(), packageName); + } + + @Override + @Deprecated + public final ActivityInfo getActivityInfo(ComponentName component, + @PackageManager.ComponentInfoFlagsBits long flags, int userId) { + return snapshot().getActivityInfo(component, flags, userId); + } + + @NonNull + @Override + @Deprecated + public final ParceledListSlice<IntentFilter> getAllIntentFilters(@NonNull String packageName) { + return snapshot().getAllIntentFilters(packageName); + } + + @Override + @Deprecated + public final List<String> getAllPackages() { + return snapshot().getAllPackages(); + } + + // NOTE: Can't remove due to unsupported app usage + @NonNull + @Override + @Deprecated + public final String[] getAppOpPermissionPackages(@NonNull String permissionName) { + return snapshot().getAppOpPermissionPackages(permissionName); + } + + @Override + @Deprecated + public final String getAppPredictionServicePackageName() { + return mService.mAppPredictionServicePackage; + } + + @PackageManager.EnabledState + @Override + @Deprecated + public final int getApplicationEnabledSetting(@NonNull String packageName, + @UserIdInt int userId) { + return snapshot().getApplicationEnabledSetting(packageName, userId); + } + + /** + * Returns true if application is not found or there was an error. Otherwise it returns the + * hidden state of the package for the given user. + */ + @Override + @Deprecated + public final boolean getApplicationHiddenSettingAsUser(@NonNull String packageName, + @UserIdInt int userId) { + return snapshot().getApplicationHiddenSettingAsUser(packageName, userId); + } + + @Override + @Deprecated + public final ApplicationInfo getApplicationInfo(String packageName, + @PackageManager.ApplicationInfoFlagsBits long flags, int userId) { + return snapshot().getApplicationInfo(packageName, flags, userId); + } + + @Override + @Deprecated + public final IArtManager getArtManager() { + return mService.mArtManagerService; + } + + @Override + @Deprecated + public final @Nullable + String getAttentionServicePackageName() { + return mService.ensureSystemPackageName(snapshot(), + mService.getPackageFromComponentString(R.string.config_defaultAttentionService)); + } + + @Override + @Deprecated + public final boolean getBlockUninstallForUser(@NonNull String packageName, + @UserIdInt int userId) { + return snapshot().getBlockUninstallForUser(packageName, userId); + } + + @Override + @Deprecated + public final int getComponentEnabledSetting(@NonNull ComponentName component, int userId) { + return snapshot().getComponentEnabledSetting(component, Binder.getCallingUid(), userId); + } + + @Override + @Deprecated + public final String getContentCaptureServicePackageName() { + return mService.ensureSystemPackageName(snapshot(), + mService.getPackageFromComponentString( + R.string.config_defaultContentCaptureService)); + } + + @Nullable + @Override + @Deprecated + public final ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries( + @NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, + @NonNull int userId) { + return snapshot().getDeclaredSharedLibraries(packageName, flags, userId); + } + + /** + * Non-Binder method, support for the backup/restore mechanism: write the default browser (etc) + * settings in its canonical XML format. Returns the default browser XML representation as a + * byte array, or null if there is none. + */ + @Override + @Deprecated + public final byte[] getDefaultAppsBackup(int userId) { + return mPreferredActivityHelper.getDefaultAppsBackup(userId); + } + + @Override + @Deprecated + public final String getDefaultTextClassifierPackageName() { + return mService.mDefaultTextClassifierPackage; + } + + @Override + @Deprecated + public final int getFlagsForUid(int uid) { + return snapshot().getFlagsForUid(uid); + } + + @Nullable + @Override + @Deprecated + public final CharSequence getHarmfulAppWarning(@NonNull String packageName, + @UserIdInt int userId) { + return snapshot().getHarmfulAppWarning(packageName, userId); + } + + @Override + @Deprecated + public final ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) { + final Computer snapshot = snapshot(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { + return null; + } + return snapshot.getHomeActivitiesAsUser(allHomeCandidates, + UserHandle.getCallingUserId()); + } + + @Deprecated + public final String getIncidentReportApproverPackageName() { + return mService.mIncidentReportApproverPackage; + } + + @Override + @Deprecated + public final int getInstallLocation() { + // allow instant app access + return android.provider.Settings.Global.getInt(mContext.getContentResolver(), + android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, + InstallLocationUtils.APP_INSTALL_AUTO); + } + + @PackageManager.InstallReason + @Override + @Deprecated + public final int getInstallReason(@NonNull String packageName, @UserIdInt int userId) { + return snapshot().getInstallReason(packageName, userId); + } + + @Override + @Nullable + @Deprecated + public final InstallSourceInfo getInstallSourceInfo(@NonNull String packageName) { + return snapshot().getInstallSourceInfo(packageName); + } + + @Override + @Deprecated + public final ParceledListSlice<ApplicationInfo> getInstalledApplications( + @PackageManager.ApplicationInfoFlagsBits long flags, int userId) { + final int callingUid = Binder.getCallingUid(); + return new ParceledListSlice<>( + snapshot().getInstalledApplications(flags, userId, callingUid)); + } + + @Override + @Deprecated + public final List<ModuleInfo> getInstalledModules(int flags) { + return mModuleInfoProvider.getInstalledModules(flags); + } + + @Override + @Deprecated + public final ParceledListSlice<PackageInfo> getInstalledPackages( + @PackageManager.PackageInfoFlagsBits long flags, int userId) { + return snapshot().getInstalledPackages(flags, userId); + } + + @Nullable + @Override + @Deprecated + public final String getInstallerPackageName(@NonNull String packageName) { + return snapshot().getInstallerPackageName(packageName); + } + + @Override + @Deprecated + public final ComponentName getInstantAppInstallerComponent() { + final Computer snapshot = snapshot(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { + return null; + } + return snapshot.getInstantAppInstallerComponent(); + } + + @Override + @Deprecated + public final @Nullable + ComponentName getInstantAppResolverComponent() { + final Computer snapshot = snapshot(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { + return null; + } + return mService.getInstantAppResolver(snapshot); + } + + @Override + @Deprecated + public final ComponentName getInstantAppResolverSettingsComponent() { + return mInstantAppResolverSettingsComponent; + } + + @Nullable + @Override + @Deprecated + public final InstrumentationInfo getInstrumentationInfo(@NonNull ComponentName component, + int flags) { + return snapshot().getInstrumentationInfo(component, flags); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<IntentFilterVerificationInfo> + getIntentFilterVerifications(String packageName) { + return ParceledListSlice.emptyList(); + } + + @Override + @Deprecated + public final int getIntentVerificationStatus(String packageName, int userId) { + return mDomainVerificationManager.getLegacyState(packageName, userId); + } + + @Nullable + @Override + @Deprecated + public final KeySet getKeySetByAlias(@NonNull String packageName, @NonNull String alias) { + return snapshot().getKeySetByAlias(packageName, alias); + } + + @Override + @Deprecated + public final ModuleInfo getModuleInfo(String packageName, + @PackageManager.ModuleInfoFlags int flags) { + return mModuleInfoProvider.getModuleInfo(packageName, flags); + } + + @Nullable + @Override + @Deprecated + public final String getNameForUid(int uid) { + return snapshot().getNameForUid(uid); + } + + @Nullable + @Override + @Deprecated + public final String[] getNamesForUids(@NonNull int[] uids) { + return snapshot().getNamesForUids(uids); + } + + @Override + @Deprecated + public final int[] getPackageGids(String packageName, + @PackageManager.PackageInfoFlagsBits long flags, int userId) { + return snapshot().getPackageGids(packageName, flags, userId); + } + + @Override + @Deprecated + public final PackageInfo getPackageInfo(String packageName, + @PackageManager.PackageInfoFlagsBits long flags, int userId) { + return snapshot().getPackageInfo(packageName, flags, userId); + } + + @Override + @Deprecated + public final PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage, + @PackageManager.PackageInfoFlagsBits long flags, int userId) { + return snapshot().getPackageInfoInternal(versionedPackage.getPackageName(), + versionedPackage.getLongVersionCode(), flags, Binder.getCallingUid(), userId); + } + + @Override + @Deprecated + public final IPackageInstaller getPackageInstaller() { + // Return installer service for internal calls. + if (PackageManagerServiceUtils.isSystemOrRoot()) { + return mInstallerService; + } + final Computer snapshot = snapshot(); + // Return null for InstantApps. + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { + return null; + } + return mInstallerService; + } + + @Override + @Deprecated + public final void getPackageSizeInfo(final String packageName, int userId, + final IPackageStatsObserver observer) { + throw new UnsupportedOperationException( + "Shame on you for calling the hidden API getPackageSizeInfo(). Shame!"); + } + + @Override + @Deprecated + public final int getPackageUid(@NonNull String packageName, + @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { + return snapshot().getPackageUid(packageName, flags, userId); + } + + /** + * <em>IMPORTANT:</em> Not all packages returned by this method may be known + * to the system. There are two conditions in which this may occur: + * <ol> + * <li>The package is on adoptable storage and the device has been removed</li> + * <li>The package is being removed and the internal structures are partially updated</li> + * </ol> + * The second is an artifact of the current data structures and should be fixed. See + * b/111075456 for one such instance. + * This binder API is cached. If the algorithm in this method changes, + * or if the underlying objecs (as returned by getSettingLPr()) change + * then the logic that invalidates the cache must be revisited. See + * calls to invalidateGetPackagesForUidCache() to locate the points at + * which the cache is invalidated. + */ + @Override + @Deprecated + public final String[] getPackagesForUid(int uid) { + final int callingUid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(uid); + snapshot().enforceCrossUserOrProfilePermission(callingUid, userId, + /* requireFullPermission */ false, + /* checkShell */ false, "getPackagesForUid"); + return snapshot().getPackagesForUid(uid); + } + + @Override + @Deprecated + public final ParceledListSlice<PackageInfo> getPackagesHoldingPermissions( + @NonNull String[] permissions, @PackageManager.PackageInfoFlagsBits long flags, + @UserIdInt int userId) { + return snapshot().getPackagesHoldingPermissions(permissions, flags, userId); + } + + // NOTE: Can't remove due to unsupported app usage + @Override + @Deprecated + public final PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) { + return mService.getPermissionGroupInfo(groupName, flags); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) { + final Computer snapshot = snapshot(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { + return ParceledListSlice.emptyList(); + } + return new ParceledListSlice<>(snapshot.getPersistentApplications(isSafeMode(), flags)); + } + + @Override + @Deprecated + public final int getPreferredActivities(List<IntentFilter> outFilters, + List<ComponentName> outActivities, String packageName) { + return mPreferredActivityHelper.getPreferredActivities(snapshot(), outFilters, + outActivities, packageName); + } + + /** + * Non-Binder method, support for the backup/restore mechanism: write the full set of preferred + * activities in its canonical XML format. Returns the XML output as a byte array, or null if + * there is none. + */ + @Override + @Deprecated + public final byte[] getPreferredActivityBackup(int userId) { + return mPreferredActivityHelper.getPreferredActivityBackup(userId); + } + + @Override + @Deprecated + public final int getPrivateFlagsForUid(int uid) { + return snapshot().getPrivateFlagsForUid(uid); + } + + @Override + @Deprecated + public final PackageManager.Property getProperty(String propertyName, String packageName, + String className) { + Objects.requireNonNull(propertyName); + Objects.requireNonNull(packageName); + PackageStateInternal packageState = snapshot().getPackageStateFiltered(packageName, + Binder.getCallingUid(), UserHandle.getCallingUserId()); + if (packageState == null) { + return null; + } + return mPackageProperty.getProperty(propertyName, packageName, className); + } + + @Nullable + @Override + @Deprecated + public final ProviderInfo getProviderInfo(@NonNull ComponentName component, + @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { + return snapshot().getProviderInfo(component, flags, userId); + } + + @Override + @Deprecated + public final ActivityInfo getReceiverInfo(ComponentName component, + @PackageManager.ComponentInfoFlagsBits long flags, int userId) { + return snapshot().getReceiverInfo(component, flags, userId); + } + + @Override + @Deprecated + public final @Nullable + String getRotationResolverPackageName() { + return mService.ensureSystemPackageName(snapshot(), + mService.getPackageFromComponentString( + R.string.config_defaultRotationResolverService)); + } + + @Nullable + @Override + @Deprecated + public final ServiceInfo getServiceInfo(@NonNull ComponentName component, + @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { + return snapshot().getServiceInfo(component, flags, userId); + } + + @Override + @Deprecated + public final @NonNull + String getServicesSystemSharedLibraryPackageName() { + return mServicesExtensionPackageName; + } + + @Override + @Deprecated + public final String getSetupWizardPackageName() { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Non-system caller"); + } + return mService.mSetupWizardPackage; + } + + @Override + @Deprecated + public final ParceledListSlice<SharedLibraryInfo> getSharedLibraries(String packageName, + @PackageManager.PackageInfoFlagsBits long flags, int userId) { + return snapshot().getSharedLibraries(packageName, flags, userId); + } + + @Override + @Deprecated + public final @NonNull + String getSharedSystemSharedLibraryPackageName() { + return mSharedSystemSharedLibraryPackageName; + } + + @Nullable + @Override + @Deprecated + public final KeySet getSigningKeySet(@NonNull String packageName) { + return snapshot().getSigningKeySet(packageName); + } + + @Override + @Deprecated + public final String getSdkSandboxPackageName() { + return mService.getSdkSandboxPackageName(); + } + + @Override + @Deprecated + public final String getSystemCaptionsServicePackageName() { + return mService.ensureSystemPackageName(snapshot(), + mService.getPackageFromComponentString( + R.string.config_defaultSystemCaptionsService)); + } + + @Nullable + @Override + @Deprecated + public final String[] getSystemSharedLibraryNames() { + return snapshot().getSystemSharedLibraryNames(); + } + + @Override + @Deprecated + public final String getSystemTextClassifierPackageName() { + return mService.mSystemTextClassifierPackageName; + } + + @Override + @Deprecated + public final int getTargetSdkVersion(@NonNull String packageName) { + return snapshot().getTargetSdkVersion(packageName); + } + + @Override + @Deprecated + public final int getUidForSharedUser(@NonNull String sharedUserName) { + return snapshot().getUidForSharedUser(sharedUserName); + } + + @SuppressLint("MissingPermission") + @Override + @Deprecated + public final String getWellbeingPackageName() { + final long identity = Binder.clearCallingIdentity(); + try { + return CollectionUtils.firstOrNull( + mContext.getSystemService(RoleManager.class).getRoleHolders( + RoleManager.ROLE_SYSTEM_WELLBEING)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + // NOTE: Can't remove due to unsupported app usage + @SuppressLint("MissingPermission") + @Override + @Deprecated + public final void grantRuntimePermission(String packageName, String permName, + final int userId) { + // Because this is accessed via the package manager service AIDL, + // go through the permission manager service AIDL + mContext.getSystemService(PermissionManager.class) + .grantRuntimePermission(packageName, permName, UserHandle.of(userId)); + } + + @Override + @Deprecated + public final boolean hasSigningCertificate(@NonNull String packageName, + @NonNull byte[] certificate, + @PackageManager.CertificateInputType int type) { + return snapshot().hasSigningCertificate(packageName, certificate, type); + } + + @Override + @Deprecated + public final boolean hasSystemFeature(String name, int version) { + return mService.hasSystemFeature(name, version); + } + + @Override + @Deprecated + public final boolean hasSystemUidErrors() { + // allow instant applications + return false; + } + + @Override + @Deprecated + public final boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate, + @PackageManager.CertificateInputType int type) { + return snapshot().hasUidSigningCertificate(uid, certificate, type); + } + + @Override + @Deprecated + public final boolean isDeviceUpgrading() { + return mService.isDeviceUpgrading(); + } + + @Override + @Deprecated + public final boolean isFirstBoot() { + return mService.isFirstBoot(); + } + + @Override + @Deprecated + public final boolean isInstantApp(String packageName, int userId) { + return snapshot().isInstantApp(packageName, userId); + } + + @Override + @Deprecated + public final boolean isOnlyCoreApps() { + return mService.isOnlyCoreApps(); + } + + @Override + @Deprecated + public final boolean isPackageAvailable(String packageName, int userId) { + return snapshot().isPackageAvailable(packageName, userId); + } + + @Override + @Deprecated + public final boolean isPackageDeviceAdminOnAnyUser(String packageName) { + return mService.isPackageDeviceAdminOnAnyUser(snapshot(), + packageName); + } + + @Override + @Deprecated + public final boolean isPackageSignedByKeySet(@NonNull String packageName, @NonNull KeySet ks) { + return snapshot().isPackageSignedByKeySet(packageName, ks); + } + + @Override + @Deprecated + public final boolean isPackageSignedByKeySetExactly(@NonNull String packageName, + @NonNull KeySet ks) { + return snapshot().isPackageSignedByKeySetExactly(packageName, ks); + } + + @Override + @Deprecated + public final boolean isPackageSuspendedForUser(@NonNull String packageName, + @UserIdInt int userId) { + return snapshot().isPackageSuspendedForUser(packageName, userId); + } + + @Override + @Deprecated + public final boolean isSafeMode() { + // allow instant applications + return mService.getSafeMode(); + } + + @Override + @Deprecated + public final boolean isStorageLow() { + return mService.isStorageLow(); + } + + @Override + @Deprecated + public final boolean isUidPrivileged(int uid) { + return snapshot().isUidPrivileged(uid); + } + + /** + * Ask the package manager to perform a dex-opt with the given compiler filter. + * <p> + * Note: exposed only for the shell command to allow moving packages explicitly to a definite + * state. + */ + @Override + @Deprecated + public final boolean performDexOptMode(String packageName, + boolean checkProfiles, String targetCompilerFilter, boolean force, + boolean bootComplete, String splitName) { + return mDexOptHelper.performDexOptMode(packageName, checkProfiles, targetCompilerFilter, + force, bootComplete, splitName); + } + + /** + * Ask the package manager to perform a dex-opt with the given compiler filter on the secondary + * dex files belonging to the given package. + * <p> + * Note: exposed only for the shell command to allow moving packages explicitly to a definite + * state. + */ + @Override + @Deprecated + public final boolean performDexOptSecondary(String packageName, String compilerFilter, + boolean force) { + return mDexOptHelper.performDexOptSecondary(packageName, compilerFilter, force); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + try { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities"); + + return new ParceledListSlice<>(snapshot().queryIntentActivitiesInternal(intent, + resolvedType, flags, userId)); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + } + + @NonNull + @Override + @Deprecated + public final ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName, + int uid, @PackageManager.ComponentInfoFlagsBits long flags, + @Nullable String metaDataKey) { + return snapshot().queryContentProviders(processName, uid, flags, metaDataKey); + } + + @NonNull + @Override + @Deprecated + public final ParceledListSlice<InstrumentationInfo> queryInstrumentation( + @NonNull String targetPackage, int flags) { + return snapshot().queryInstrumentation(targetPackage, flags); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<ResolveInfo> queryIntentActivityOptions( + ComponentName caller, Intent[] specifics, String[] specificTypes, Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + return new ParceledListSlice<>(mResolveIntentHelper.queryIntentActivityOptionsInternal( + snapshot(), caller, specifics, specificTypes, intent, resolvedType, flags, + userId)); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + return new ParceledListSlice<>(mResolveIntentHelper.queryIntentContentProvidersInternal( + snapshot(), intent, resolvedType, flags, userId)); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + return new ParceledListSlice<>(mResolveIntentHelper.queryIntentReceiversInternal( + snapshot(), intent, resolvedType, flags, userId, Binder.getCallingUid())); + } + + @Override + @Deprecated + public final @NonNull + ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + final int callingUid = Binder.getCallingUid(); + return new ParceledListSlice<>(snapshot().queryIntentServicesInternal( + intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/)); + } + + @Override + @Deprecated + public final void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) { + snapshot().querySyncProviders(isSafeMode(), outNames, outInfo); + } + + @Override + @Deprecated + public final void removePermission(String permName) { + // Because this is accessed via the package manager service AIDL, + // go through the permission manager service AIDL + mContext.getSystemService(PermissionManager.class).removePermission(permName); + } + + @Override + @Deprecated + public final void replacePreferredActivity(IntentFilter filter, int match, + ComponentName[] set, ComponentName activity, int userId) { + mPreferredActivityHelper.replacePreferredActivity(snapshot(), + new WatchedIntentFilter(filter), match, set, activity, userId); + } + + @Override + @Deprecated + public final ProviderInfo resolveContentProvider(String name, + @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + return snapshot().resolveContentProvider(name, flags, userId, Binder.getCallingUid()); + } + + @Override + @Deprecated + public final void resetApplicationPreferences(int userId) { + mPreferredActivityHelper.resetApplicationPreferences(userId); + } + + @Override + @Deprecated + public final ResolveInfo resolveIntent(Intent intent, String resolvedType, + @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + return mResolveIntentHelper.resolveIntentInternal(snapshot(), intent, + resolvedType, flags, 0 /*privateResolveFlags*/, userId, false, + Binder.getCallingUid()); + } + + @Override + @Deprecated + public final ResolveInfo resolveService(Intent intent, String resolvedType, + @PackageManager.ResolveInfoFlagsBits long flags, int userId) { + final int callingUid = Binder.getCallingUid(); + return mResolveIntentHelper.resolveServiceInternal(snapshot(), intent, + resolvedType, flags, userId, callingUid); + } + + @Override + @Deprecated + public final void restoreDefaultApps(byte[] backup, int userId) { + mPreferredActivityHelper.restoreDefaultApps(backup, userId); + } + + @Override + @Deprecated + public final void restorePreferredActivities(byte[] backup, int userId) { + mPreferredActivityHelper.restorePreferredActivities(backup, userId); + } + + @Override + @Deprecated + public final void setHomeActivity(ComponentName comp, int userId) { + mPreferredActivityHelper.setHomeActivity(snapshot(), comp, userId); + } + + @Override + @Deprecated + public final void setLastChosenActivity(Intent intent, String resolvedType, int flags, + IntentFilter filter, int match, ComponentName activity) { + mPreferredActivityHelper.setLastChosenActivity(snapshot(), intent, resolvedType, + flags, new WatchedIntentFilter(filter), match, activity); + } + + @Override + @Deprecated + public final boolean updateIntentVerificationStatus(String packageName, int status, + int userId) { + return mDomainVerificationManager.setLegacyUserState(packageName, userId, status); + } + + @Override + @Deprecated + public final void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) { + DomainVerificationProxyV1.queueLegacyVerifyResult(mContext, mDomainVerificationConnection, + id, verificationCode, failedDomains, Binder.getCallingUid()); + } + + @Override + @Deprecated + public final boolean canPackageQuery(@NonNull String sourcePackageName, + @NonNull String targetPackageName, @UserIdInt int userId) { + return snapshot().canPackageQuery(sourcePackageName, targetPackageName, userId); + } + + @Override + @Deprecated + public final void deletePreloadsFileCache() throws RemoteException { + mService.deletePreloadsFileCache(); + } + + @Override + @Deprecated + public final void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden) + throws RemoteException { + mService.setSystemAppHiddenUntilInstalled(snapshot(), packageName, hidden); + } + + @Override + @Deprecated + public final boolean setSystemAppInstallState(String packageName, + boolean installed, int userId) throws RemoteException { + return mService.setSystemAppInstallState(snapshot(), packageName, installed, userId); + } + + @Override + @Deprecated + public final void finishPackageInstall(int token, boolean didLaunch) throws RemoteException { + mService.finishPackageInstall(token, didLaunch); + } +} diff --git a/services/core/java/com/android/server/pm/IncrementalProgressListener.java b/services/core/java/com/android/server/pm/IncrementalProgressListener.java index fa11924218d4..703bbda92182 100644 --- a/services/core/java/com/android/server/pm/IncrementalProgressListener.java +++ b/services/core/java/com/android/server/pm/IncrementalProgressListener.java @@ -33,7 +33,8 @@ final class IncrementalProgressListener extends IPackageLoadingProgressCallback. @Override public void onPackageLoadingProgressChanged(float progress) { - PackageStateInternal packageState = mPm.getPackageStateInternal(mPackageName); + PackageStateInternal packageState = mPm.snapshotComputer() + .getPackageStateInternal(mPackageName); if (packageState == null) { return; } diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java index 6dbe9b6f89f6..f452b2967327 100644 --- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java +++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java @@ -170,7 +170,7 @@ final class InitAndSystemPackageHelper { } } OverlayConfig overlayConfig = OverlayConfig.initializeSystemInstance( - consumer -> mPm.forEachPackage( + consumer -> mPm.forEachPackage(mPm.snapshotComputer(), pkg -> consumer.accept(pkg, pkg.isSystem(), apkInApexPreInstalledPaths.get(pkg.getPackageName())))); // Prune any system packages that no longer exist. diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 8667ffd7930c..b39b24f6defa 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -527,8 +527,10 @@ final class InstallPackageHelper { + android.Manifest.permission.INSTALL_PACKAGES + "."); } PackageSetting pkgSetting; - mPm.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, - true /* checkShell */, "installExistingPackage for user " + userId); + final Computer preLockSnapshot = mPm.snapshotComputer(); + preLockSnapshot.enforceCrossUserPermission(callingUid, userId, + true /* requireFullPermission */, true /* checkShell */, + "installExistingPackage for user " + userId); if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { return PackageManager.INSTALL_FAILED_USER_RESTRICTED; } @@ -543,11 +545,12 @@ final class InstallPackageHelper { // writer synchronized (mPm.mLock) { + final Computer snapshot = mPm.snapshotComputer(); pkgSetting = mPm.mSettings.getPackageLPr(packageName); if (pkgSetting == null) { return PackageManager.INSTALL_FAILED_INVALID_URI; } - if (!mPm.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) { + if (!snapshot.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) { // only allow the existing package to be used if it's installed as a full // application for at least one user boolean installAllowed = false; @@ -597,7 +600,8 @@ final class InstallPackageHelper { mAppDataHelper.prepareAppDataAfterInstallLIF(pkgSetting.getPkg()); } } - mPm.sendPackageAddedForUser(packageName, pkgSetting, userId, DataLoaderType.NONE); + mPm.sendPackageAddedForUser(mPm.snapshotComputer(), packageName, pkgSetting, userId, + DataLoaderType.NONE); synchronized (mPm.mLock) { mPm.updateSequenceNumberLP(pkgSetting, new int[]{ userId }); } @@ -1902,8 +1906,8 @@ final class InstallPackageHelper { AndroidPackage oldPackage = mPm.mPackages.get(packageName); // Set the update and install times - PackageStateInternal deletedPkgSetting = mPm.getPackageStateInternal( - oldPackage.getPackageName()); + PackageStateInternal deletedPkgSetting = mPm.snapshotComputer() + .getPackageStateInternal(oldPackage.getPackageName()); reconciledPkg.mPkgSetting .setFirstInstallTimeFromReplaced(deletedPkgSetting, request.mAllUsers) .setLastUpdateTime(System.currentTimeMillis()); @@ -2571,9 +2575,10 @@ final class InstallPackageHelper { size = i; mPm.mPendingBroadcasts.clear(); } + final Computer snapshot = mPm.snapshotComputer(); // Send broadcasts for (int i = 0; i < size; i++) { - mPm.sendPackageChangedBroadcast(packages[i], true /* dontKillApp */, + mPm.sendPackageChangedBroadcast(snapshot, packages[i], true /* dontKillApp */, components[i], uids[i], null /* reason */); } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); @@ -2592,7 +2597,7 @@ final class InstallPackageHelper { final boolean update = res.mRemovedInfo != null && res.mRemovedInfo.mRemovedPackage != null; final String packageName = res.mName; final PackageStateInternal pkgSetting = - succeeded ? mPm.getPackageStateInternal(packageName) : null; + succeeded ? mPm.snapshotComputer().getPackageStateInternal(packageName) : null; final boolean removedBeforeUpdate = (pkgSetting == null) || (pkgSetting.isSystem() && !pkgSetting.getPath().getPath().equals( res.mPkg.getPath())); @@ -2690,9 +2695,9 @@ final class InstallPackageHelper { // sendPackageAddedForNewUsers also deals with system apps int appId = UserHandle.getAppId(res.mUid); boolean isSystem = res.mPkg.isSystem(); - mPm.sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload, - virtualPreload /*startReceiver*/, appId, firstUserIds, firstInstantUserIds, - dataLoaderType); + mPm.sendPackageAddedForNewUsers(mPm.snapshotComputer(), packageName, + isSystem || virtualPreload, virtualPreload /*startReceiver*/, appId, + firstUserIds, firstInstantUserIds, dataLoaderType); // Send added for users that don't see the package for the first time Bundle extras = new Bundle(); @@ -2705,7 +2710,8 @@ final class InstallPackageHelper { final SparseArray<int[]> newBroadcastAllowList; synchronized (mPm.mLock) { newBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList( - mPm.getPackageStateInternal(packageName, Process.SYSTEM_UID), + mPm.snapshotComputer() + .getPackageStateInternal(packageName, Process.SYSTEM_UID), updateUserIds, mPm.mSettings.getPackagesLocked()); } mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, @@ -2807,11 +2813,12 @@ final class InstallPackageHelper { } } else if (!ArrayUtils.isEmpty(res.mLibraryConsumers)) { // 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 && res.mPkg.getStaticSharedLibName() != null; for (int i = 0; i < res.mLibraryConsumers.size(); i++) { AndroidPackage pkg = res.mLibraryConsumers.get(i); // send broadcast that all consumers of the static shared library have changed - mPm.sendPackageChangedBroadcast(pkg.getPackageName(), dontKillApp, + mPm.sendPackageChangedBroadcast(snapshot, pkg.getPackageName(), dontKillApp, new ArrayList<>(Collections.singletonList(pkg.getPackageName())), pkg.getUid(), null); } diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java index 0ffc1ed9e90c..230f5558b37d 100644 --- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java +++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import android.annotation.NonNull; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.ModuleInfo; @@ -25,6 +26,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; @@ -58,7 +60,7 @@ public class ModuleInfoProvider { private static final String MODULE_METADATA_KEY = "android.content.pm.MODULE_METADATA"; private final Context mContext; - private final IPackageManager mPackageManager; + private IPackageManager mPackageManager; private final ApexManager mApexManager; private final Map<String, ModuleInfo> mModuleInfo; @@ -66,9 +68,8 @@ public class ModuleInfoProvider { private volatile boolean mMetadataLoaded; private volatile String mPackageName; - ModuleInfoProvider(Context context, IPackageManager packageManager) { + ModuleInfoProvider(Context context) { mContext = context; - mPackageManager = packageManager; mApexManager = ApexManager.getInstance(); mModuleInfo = new ArrayMap<>(); } @@ -77,12 +78,20 @@ public class ModuleInfoProvider { public ModuleInfoProvider( XmlResourceParser metadata, Resources resources, ApexManager apexManager) { mContext = null; - mPackageManager = null; mApexManager = apexManager; mModuleInfo = new ArrayMap<>(); loadModuleMetadata(metadata, resources); } + @NonNull + private IPackageManager getPackageManager() { + if (mPackageManager == null) { + mPackageManager = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + } + return mPackageManager; + } + /** Called by the {@code PackageManager} when it has completed its boot sequence */ public void systemReady() { mPackageName = mContext.getResources().getString( @@ -95,7 +104,7 @@ public class ModuleInfoProvider { final Resources packageResources; final PackageInfo pi; try { - pi = mPackageManager.getPackageInfo(mPackageName, + pi = getPackageManager().getPackageInfo(mPackageName, PackageManager.GET_META_DATA, UserHandle.USER_SYSTEM); Context packageContext = mContext.createPackageContext(mPackageName, 0); @@ -183,7 +192,7 @@ public class ModuleInfoProvider { List<PackageInfo> allPackages; try { - allPackages = mPackageManager.getInstalledPackages( + allPackages = getPackageManager().getInstalledPackages( flags | PackageManager.MATCH_APEX, UserHandle.getCallingUserId()).getList(); } catch (RemoteException e) { Slog.w(TAG, "Unable to retrieve all package names", e); diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java index 5fc90b1d994f..c5ca06cc7b84 100644 --- a/services/core/java/com/android/server/pm/MovePackageHelper.java +++ b/services/core/java/com/android/server/pm/MovePackageHelper.java @@ -57,6 +57,8 @@ import com.android.internal.os.SomeArgs; import com.android.internal.util.FrameworkStatsLog; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.AndroidPackageUtils; +import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.pkg.PackageStateUtils; import java.io.File; import java.util.Objects; @@ -77,81 +79,74 @@ public final class MovePackageHelper { final StorageManager storage = mPm.mInjector.getSystemService(StorageManager.class); final PackageManager pm = mPm.mContext.getPackageManager(); - final String currentVolumeUuid; - final File codeFile; - final InstallSource installSource; - final String packageAbiOverride; - final int appId; - final String seinfo; - final String label; - final int targetSdkVersion; - final PackageFreezer freezer; - final int[] installedUserIds; - final boolean isCurrentLocationExternal; - final String fromCodePath; + Computer snapshot = mPm.snapshotComputer(); + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); + if (packageState == null + || packageState.getPkg() == null + || snapshot.shouldFilterApplication(packageState, callingUid, user.getIdentifier())) { + throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package"); + } + final AndroidPackage pkg = packageState.getPkg(); + if (pkg.isSystem()) { + throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, + "Cannot move system application"); + } - // reader - synchronized (mPm.mLock) { - final AndroidPackage pkg = mPm.mPackages.get(packageName); - final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); - if (pkg == null - || ps == null - || mPm.shouldFilterApplication(ps, callingUid, user.getIdentifier())) { - throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package"); - } - if (pkg.isSystem()) { - throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, - "Cannot move system application"); - } + final boolean isInternalStorage = VolumeInfo.ID_PRIVATE_INTERNAL.equals(volumeUuid); + final boolean allow3rdPartyOnInternal = mPm.mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allow3rdPartyAppOnInternal); + if (isInternalStorage && !allow3rdPartyOnInternal) { + throw new PackageManagerException(MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL, + "3rd party apps are not allowed on internal storage"); + } - final boolean isInternalStorage = VolumeInfo.ID_PRIVATE_INTERNAL.equals(volumeUuid); - final boolean allow3rdPartyOnInternal = mPm.mContext.getResources().getBoolean( - com.android.internal.R.bool.config_allow3rdPartyAppOnInternal); - if (isInternalStorage && !allow3rdPartyOnInternal) { - throw new PackageManagerException(MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL, - "3rd party apps are not allowed on internal storage"); - } - currentVolumeUuid = ps.getVolumeUuid(); + final String currentVolumeUuid = packageState.getVolumeUuid(); - final File probe = new File(pkg.getPath()); - final File probeOat = new File(probe, "oat"); - if (!probe.isDirectory() || !probeOat.isDirectory()) { - throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, - "Move only supported for modern cluster style installs"); - } + final File probe = new File(pkg.getPath()); + final File probeOat = new File(probe, "oat"); + if (!probe.isDirectory() || !probeOat.isDirectory()) { + throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, + "Move only supported for modern cluster style installs"); + } - if (Objects.equals(currentVolumeUuid, volumeUuid)) { - throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, - "Package already moved to " + volumeUuid); - } - if (!pkg.isExternalStorage() && mPm.isPackageDeviceAdminOnAnyUser(packageName)) { - throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN, - "Device admin cannot be moved"); - } + if (Objects.equals(currentVolumeUuid, volumeUuid)) { + throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, + "Package already moved to " + volumeUuid); + } + if (!pkg.isExternalStorage() + && mPm.isPackageDeviceAdminOnAnyUser(snapshot, packageName)) { + throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN, + "Device admin cannot be moved"); + } - if (mPm.mFrozenPackages.containsKey(packageName)) { - throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, - "Failed to move already frozen package"); - } + if (snapshot.getFrozenPackages().containsKey(packageName)) { + throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, + "Failed to move already frozen package"); + } - isCurrentLocationExternal = pkg.isExternalStorage(); - codeFile = new File(pkg.getPath()); - installSource = ps.getInstallSource(); - packageAbiOverride = ps.getCpuAbiOverride(); - appId = UserHandle.getAppId(pkg.getUid()); - seinfo = AndroidPackageUtils.getSeInfo(pkg, ps); - label = String.valueOf(pm.getApplicationLabel( - AndroidPackageUtils.generateAppInfoWithoutState(pkg))); - targetSdkVersion = pkg.getTargetSdkVersion(); + final boolean isCurrentLocationExternal = pkg.isExternalStorage(); + final File codeFile = new File(pkg.getPath()); + final InstallSource installSource = packageState.getInstallSource(); + final String packageAbiOverride = packageState.getCpuAbiOverride(); + final int appId = UserHandle.getAppId(pkg.getUid()); + final String seinfo = AndroidPackageUtils.getSeInfo(pkg, packageState); + final String label = String.valueOf(pm.getApplicationLabel( + AndroidPackageUtils.generateAppInfoWithoutState(pkg))); + final int targetSdkVersion = pkg.getTargetSdkVersion(); + final int[] installedUserIds = PackageStateUtils.queryInstalledUsers(packageState, + mPm.mUserManager.getUserIds(), true); + final String fromCodePath; + if (codeFile.getParentFile().getName().startsWith( + PackageManagerService.RANDOM_DIR_PREFIX)) { + fromCodePath = codeFile.getParentFile().getAbsolutePath(); + } else { + fromCodePath = codeFile.getAbsolutePath(); + } + + final PackageFreezer freezer; + synchronized (mPm.mLock) { freezer = mPm.freezePackage(packageName, "movePackageInternal"); - installedUserIds = ps.queryInstalledUsers(mPm.mUserManager.getUserIds(), true); - if (codeFile.getParentFile().getName().startsWith( - PackageManagerService.RANDOM_DIR_PREFIX)) { - fromCodePath = codeFile.getParentFile().getAbsolutePath(); - } else { - fromCodePath = codeFile.getAbsolutePath(); - } } final Bundle extras = new Bundle(); diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index bd0091480caf..cc4a76034b2b 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -131,8 +131,9 @@ public class OtaDexoptService extends IOtaDexopt.Stub { Predicate<PackageStateInternal> isPlatformPackage = pkgSetting -> PLATFORM_PACKAGE_NAME.equals(pkgSetting.getPkg().getPackageName()); // Important: the packages we need to run with ab-ota compiler-reason. + final Computer snapshot = mPackageManagerService.snapshotComputer(); final Collection<? extends PackageStateInternal> allPackageStates = - mPackageManagerService.getPackageStates().values(); + snapshot.getPackageStates().values(); important = DexOptHelper.getPackagesForDexopt(allPackageStates,mPackageManagerService, DEBUG_DEXOPT); // Remove Platform Package from A/B OTA b/160735835. @@ -165,7 +166,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: " + DexOptHelper.packagesToString(others)); for (PackageStateInternal pkg : others) { - mPackageManagerService.deleteOatArtifactsOfPackage(pkg.getPackageName()); + mPackageManagerService.deleteOatArtifactsOfPackage(snapshot, pkg.getPackageName()); } } long spaceAvailableNow = getAvailableSpace(); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 6613f016f66a..4e702e2c9df5 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -597,8 +597,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements String installerAttributionTag, int userId) throws IOException { final int callingUid = Binder.getCallingUid(); - mPm.enforceCrossUserPermission( - callingUid, userId, true, true, "createSession"); + final Computer snapshot = mPm.snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "createSession"); if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { throw new SecurityException("User restriction prevents installing"); @@ -663,7 +663,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements params.installFlags &= ~PackageManager.INSTALL_ALL_USERS; params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0 - && !mPm.isCallerVerifier(callingUid)) { + && !mPm.isCallerVerifier(snapshot, callingUid)) { params.installFlags &= ~PackageManager.INSTALL_VIRTUAL_PRELOAD; } if (mContext.checkCallingOrSelfPermission( @@ -676,7 +676,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements String originatingPackageName = null; if (params.originatingUid != SessionParams.UID_UNKNOWN && params.originatingUid != callingUid) { - String[] packages = mPm.mIPackageManager.getPackagesForUid(params.originatingUid); + String[] packages = snapshot.getPackagesForUid(params.originatingUid); if (packages != null && packages.length > 0) { // Choose an arbitrary representative package in the case of a shared UID. originatingPackageName = packages[0]; @@ -727,7 +727,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0 && !isCalledBySystemOrShell(callingUid) - && (mPm.mIPackageManager.getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) + && (snapshot.getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) == 0) { throw new SecurityException( "Only system apps could use the PackageManager.INSTALL_INSTANT_APP flag."); @@ -1038,11 +1038,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements return "smdl" + sessionId + ".tmp"; } - private boolean shouldFilterSession(int uid, SessionInfo info) { + private boolean shouldFilterSession(@NonNull Computer snapshot, int uid, SessionInfo info) { if (info == null) { return false; } - return uid != info.getInstallerUid() && !mPm.canQueryPackage(uid, info.getAppPackageName()); + return uid != info.getInstallerUid() + && !snapshot.canQueryPackage(uid, info.getAppPackageName()); } @Override @@ -1055,7 +1056,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements ? session.generateInfoForCaller(true /* includeIcon */, callingUid) : null; } - return shouldFilterSession(callingUid, result) ? null : result; + return shouldFilterSession(mPm.snapshotComputer(), callingUid, result) ? null : result; } @Override @@ -1070,15 +1071,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } } - result.removeIf(info -> shouldFilterSession(callingUid, info)); + final Computer snapshot = mPm.snapshotComputer(); + result.removeIf(info -> shouldFilterSession(snapshot, callingUid, info)); return new ParceledListSlice<>(result); } @Override public ParceledListSlice<SessionInfo> getAllSessions(int userId) { final int callingUid = Binder.getCallingUid(); - mPm.enforceCrossUserPermission( - callingUid, userId, true, false, "getAllSessions"); + final Computer snapshot = mPm.snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, true, false, "getAllSessions"); final List<SessionInfo> result = new ArrayList<>(); synchronized (mSessions) { @@ -1090,15 +1092,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } } - result.removeIf(info -> shouldFilterSession(callingUid, info)); + result.removeIf(info -> shouldFilterSession(snapshot, callingUid, info)); return new ParceledListSlice<>(result); } @Override public ParceledListSlice<SessionInfo> getMySessions(String installerPackageName, int userId) { - mPm.enforceCrossUserPermission( - Binder.getCallingUid(), userId, true, false, "getMySessions"); - mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName); + final Computer snapshot = mPm.snapshotComputer(); + final int callingUid = Binder.getCallingUid(); + snapshot.enforceCrossUserPermission(callingUid, userId, true, false, "getMySessions"); + mAppOps.checkPackage(callingUid, installerPackageName); final List<SessionInfo> result = new ArrayList<>(); synchronized (mSessions) { @@ -1120,8 +1123,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements @Override public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags, IntentSender statusReceiver, int userId) { + final Computer snapshot = mPm.snapshotComputer(); final int callingUid = Binder.getCallingUid(); - mPm.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); + snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) { mAppOps.checkPackage(callingUid, callerPackageName); } @@ -1154,8 +1158,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements .setAdmin(callerPackageName) .write(); } else { - ApplicationInfo appInfo = mPm.mIPackageManager - .getApplicationInfo(callerPackageName, 0, userId); + ApplicationInfo appInfo = snapshot.getApplicationInfo(callerPackageName, 0, userId); if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { mContext.enforceCallingOrSelfPermission(Manifest.permission.REQUEST_DELETE_PACKAGES, null); @@ -1174,7 +1177,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements String callerPackageName, IntentSender statusReceiver, int userId) { final int callingUid = Binder.getCallingUid(); mContext.enforceCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES, null); - mPm.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); + final Computer snapshot = mPm.snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) { mAppOps.checkPackage(callingUid, callerPackageName); } @@ -1206,8 +1210,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements @Override public void registerCallback(IPackageInstallerCallback callback, int userId) { - mPm.enforceCrossUserPermission( - Binder.getCallingUid(), userId, true, false, "registerCallback"); + final Computer snapshot = mPm.snapshotComputer(); + snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + "registerCallback"); registerCallback(callback, eventUserId -> userId == eventUserId); } @@ -1295,13 +1300,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } - private boolean shouldFilterSession(int uid, int sessionId) { + private boolean shouldFilterSession(@NonNull Computer snapshot, int uid, int sessionId) { final PackageInstallerSession session = getSession(sessionId); if (session == null) { return false; } return uid != session.getInstallerUid() - && !mPm.canQueryPackage(uid, session.getPackageName()); + && !snapshot.canQueryPackage(uid, session.getPackageName()); } static class PackageDeleteObserverAdapter extends PackageDeleteObserver { @@ -1454,11 +1459,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements final int sessionId = msg.arg1; final int userId = msg.arg2; final int n = mCallbacks.beginBroadcast(); + final Computer snapshot = mPm.snapshotComputer(); for (int i = 0; i < n; i++) { final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i); final BroadcastCookie cookie = (BroadcastCookie) mCallbacks.getBroadcastCookie(i); if (cookie.userCheck.test(userId) - && !shouldFilterSession(cookie.callingUid, sessionId)) { + && !shouldFilterSession(snapshot, cookie.callingUid, sessionId)) { try { invokeCallback(callback, msg); } catch (RemoteException ignored) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 35a7eaf29ddc..68be64fdba0d 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -126,6 +126,7 @@ import android.system.StructStat; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.EventLog; import android.util.ExceptionUtils; import android.util.IntArray; import android.util.MathUtils; @@ -859,7 +860,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return USER_ACTION_NOT_NEEDED; } - if (mPm.isInstallDisabledForPackage(getInstallerPackageName(), mInstallerUid, userId)) { + if (snapshot.isInstallDisabledForPackage(getInstallerPackageName(), mInstallerUid, + userId)) { // show the installer to account for device poslicy or unknown sources use cases return USER_ACTION_REQUIRED; } @@ -2861,7 +2863,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { inheritFileLocked(mResolvedBaseFile); // Collect the requiredSplitTypes from base CollectionUtils.addAll(requiredSplitTypes, existing.getBaseRequiredSplitTypes()); - } else { + } else if ((params.installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) { + EventLog.writeEvent(0x534e4554, "219044664"); + // Installing base.apk. Make sure the app is restarted. params.setDontKillApp(false); } @@ -3752,7 +3756,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { }; if (!manualStartAndDestroy) { - final PerUidReadTimeouts[] perUidReadTimeouts = mPm.getPerUidReadTimeouts(); + final PerUidReadTimeouts[] perUidReadTimeouts = + mPm.getPerUidReadTimeouts(mPm.snapshotComputer()); final StorageHealthCheckParams healthCheckParams = new StorageHealthCheckParams(); healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS; diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java new file mode 100644 index 000000000000..2b733754685e --- /dev/null +++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java @@ -0,0 +1,751 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; +import static android.content.pm.PackageManager.RESTRICTION_NONE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.AuxiliaryResolveInfo; +import android.content.pm.Checksum; +import android.content.pm.IOnChecksumsReadyListener; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; +import android.content.pm.ProcessInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.SuspendDialogInfo; +import android.os.Binder; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Process; +import android.os.storage.StorageManager; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.SparseArray; + +import com.android.server.pm.dex.DexManager; +import com.android.server.pm.dex.DynamicCodeLogger; +import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.pm.permission.PermissionManagerServiceInternal; +import com.android.server.pm.pkg.AndroidPackageApi; +import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.pkg.PackageStateUtils; +import com.android.server.pm.pkg.SharedUserApi; +import com.android.server.pm.pkg.component.ParsedMainComponent; +import com.android.server.pm.pkg.mutate.PackageStateMutator; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +/** + * Internal manager variant of {@link IPackageManagerBase}. See that class for info. + * {@link PackageManagerInternal} should eventually passing in a snapshot instance, deprecating + * this class, but that requires much larger refactor. + */ +abstract class PackageManagerInternalBase extends PackageManagerInternal { + + @NonNull + private final PackageManagerService mService; + + public PackageManagerInternalBase(@NonNull PackageManagerService service) { + mService = service; + } + + @NonNull protected abstract Context getContext(); + @NonNull protected abstract PermissionManagerServiceInternal getPermissionManager(); + @NonNull protected abstract AppDataHelper getAppDataHelper(); + @NonNull protected abstract PackageObserverHelper getPackageObserverHelper(); + @NonNull protected abstract ResolveIntentHelper getResolveIntentHelper(); + @NonNull protected abstract SuspendPackageHelper getSuspendPackageHelper(); + @NonNull protected abstract ProtectedPackages getProtectedPackages(); + @NonNull protected abstract UserNeedsBadgingCache getUserNeedsBadging(); + @NonNull protected abstract InstantAppRegistry getInstantAppRegistry(); + @NonNull protected abstract ApexManager getApexManager(); + @NonNull protected abstract DexManager getDexManager(); + + @Override + public final Computer snapshot() { + return mService.snapshotComputer(); + } + + @Override + @Deprecated + public final List<ApplicationInfo> getInstalledApplications( + @PackageManager.ApplicationInfoFlagsBits long flags, int userId, int callingUid) { + return snapshot().getInstalledApplications(flags, userId, callingUid); + } + + @Override + @Deprecated + public final boolean isInstantApp(String packageName, int userId) { + return snapshot().isInstantApp(packageName, userId); + } + + @Override + @Deprecated + public final String getInstantAppPackageName(int uid) { + return snapshot().getInstantAppPackageName(uid); + } + + @Override + @Deprecated + public final boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) { + return snapshot().filterAppAccess(pkg, callingUid, userId); + } + + @Override + @Deprecated + public final boolean filterAppAccess(String packageName, int callingUid, int userId) { + return snapshot().filterAppAccess(packageName, callingUid, userId); + } + + @Override + @Deprecated + public final boolean filterAppAccess(int uid, int callingUid) { + return snapshot().filterAppAccess(uid, callingUid); + } + + @Nullable + @Override + @Deprecated + public final int[] getVisibilityAllowList(@NonNull String packageName, int userId) { + return snapshot().getVisibilityAllowList(packageName, userId); + } + + @Override + @Deprecated + public final boolean canQueryPackage(int callingUid, @Nullable String packageName) { + return snapshot().canQueryPackage(callingUid, packageName); + } + + @Override + @Deprecated + public final AndroidPackage getPackage(String packageName) { + return snapshot().getPackage(packageName); + } + + @Nullable + @Override + @Deprecated + public final AndroidPackageApi getAndroidPackage(@NonNull String packageName) { + return snapshot().getPackage(packageName); + } + + @Override + @Deprecated + public final AndroidPackage getPackage(int uid) { + return snapshot().getPackage(uid); + } + + @Override + @Deprecated + public final List<AndroidPackage> getPackagesForAppId(int appId) { + return snapshot().getPackagesForAppId(appId); + } + + @Nullable + @Override + @Deprecated + public final PackageStateInternal getPackageStateInternal(String packageName) { + return snapshot().getPackageStateInternal(packageName); + } + + @NonNull + @Override + @Deprecated + public final ArrayMap<String, ? extends PackageStateInternal> getPackageStates() { + return snapshot().getPackageStates(); + } + + @Override + @Deprecated + public final void removePackageListObserver(PackageListObserver observer) { + getPackageObserverHelper().removeObserver(observer); + } + + @Override + @Deprecated + public final PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) { + return snapshot().getDisabledSystemPackage(packageName); + } + + @Override + @Deprecated + public final @NonNull String[] getKnownPackageNames(int knownPackage, int userId) { + return mService.getKnownPackageNamesInternal(snapshot(), knownPackage, userId); + } + + @Override + @Deprecated + public final void setKeepUninstalledPackages(final List<String> packageList) { + mService.setKeepUninstalledPackagesInternal(snapshot(), packageList); + } + + @Override + @Deprecated + public final boolean isPermissionsReviewRequired(String packageName, int userId) { + return getPermissionManager().isPermissionsReviewRequired(packageName, userId); + } + + @Override + @Deprecated + public final PackageInfo getPackageInfo(String packageName, + @PackageManager.PackageInfoFlagsBits long flags, int filterCallingUid, int userId) { + return snapshot().getPackageInfoInternal(packageName, + PackageManager.VERSION_CODE_HIGHEST, flags, filterCallingUid, userId); + } + + @Override + @Deprecated + public final Bundle getSuspendedPackageLauncherExtras(String packageName, int userId) { + return getSuspendPackageHelper().getSuspendedPackageLauncherExtras(snapshot(), packageName, + userId, Binder.getCallingUid()); + } + + @Override + @Deprecated + public final boolean isPackageSuspended(String packageName, int userId) { + return getSuspendPackageHelper().isPackageSuspended(snapshot(), packageName, userId, + Binder.getCallingUid()); + } + + @Override + @Deprecated + public final void removeNonSystemPackageSuspensions(String packageName, int userId) { + getSuspendPackageHelper().removeSuspensionsBySuspendingPackage(snapshot(), + new String[]{packageName}, + (suspendingPackage) -> !PackageManagerService.PLATFORM_PACKAGE_NAME.equals( + suspendingPackage), + userId); + } + + @Override + @Deprecated + public final void removeDistractingPackageRestrictions(String packageName, int userId) { + mService.removeDistractingPackageRestrictions(snapshot(), new String[]{packageName}, + userId); + } + + @Override + @Deprecated + public final void removeAllDistractingPackageRestrictions(int userId) { + mService.removeAllDistractingPackageRestrictions(snapshot(), userId); + } + + @Override + @Deprecated + public final String getSuspendingPackage(String suspendedPackage, int userId) { + return getSuspendPackageHelper().getSuspendingPackage(snapshot(), suspendedPackage, userId, + Binder.getCallingUid()); + } + + @Override + @Deprecated + public final SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, + String suspendingPackage, int userId) { + return getSuspendPackageHelper().getSuspendedDialogInfo(snapshot(), suspendedPackage, + suspendingPackage, userId, Binder.getCallingUid()); + } + + @Override + @Deprecated + public final int getDistractingPackageRestrictions(String packageName, int userId) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + return (packageState == null) ? RESTRICTION_NONE + : packageState.getUserStateOrDefault(userId).getDistractionFlags(); + } + + @Override + @Deprecated + public final int getPackageUid(String packageName, + @PackageManager.PackageInfoFlagsBits long flags, int userId) { + return snapshot().getPackageUidInternal(packageName, flags, userId, Process.SYSTEM_UID); + } + + @Override + @Deprecated + public final ApplicationInfo getApplicationInfo(String packageName, + @PackageManager.ApplicationInfoFlagsBits long flags, int filterCallingUid, int userId) { + return snapshot().getApplicationInfoInternal(packageName, flags, filterCallingUid, userId); + } + + @Override + @Deprecated + public final ActivityInfo getActivityInfo(ComponentName component, + @PackageManager.ComponentInfoFlagsBits long flags, int filterCallingUid, int userId) { + return snapshot().getActivityInfoInternal(component, flags, filterCallingUid, userId); + } + + @Override + @Deprecated + public final List<ResolveInfo> queryIntentActivities( + Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, + int filterCallingUid, int userId) { + return snapshot().queryIntentActivitiesInternal(intent, resolvedType, flags, userId); + } + + @Override + @Deprecated + public final List<ResolveInfo> queryIntentReceivers(Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, + int filterCallingUid, int userId) { + return getResolveIntentHelper().queryIntentReceiversInternal( + snapshot(), intent, resolvedType, flags, userId, filterCallingUid); + } + + @Override + @Deprecated + public final List<ResolveInfo> queryIntentServices( + Intent intent, @PackageManager.ResolveInfoFlagsBits long flags, int callingUid, + int userId) { + final String resolvedType = intent.resolveTypeIfNeeded(getContext().getContentResolver()); + return snapshot().queryIntentServicesInternal(intent, resolvedType, flags, userId, + callingUid, false); + } + + @Override + @Deprecated + public final ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, + int userId) { + return snapshot().getHomeActivitiesAsUser(allHomeCandidates, userId); + } + + @Override + @Deprecated + public final ComponentName getDefaultHomeActivity(int userId) { + return snapshot().getDefaultHomeActivity(userId); + } + + @Override + @Deprecated + public final ComponentName getSystemUiServiceComponent() { + return ComponentName.unflattenFromString(getContext().getResources().getString( + com.android.internal.R.string.config_systemUIServiceComponent)); + } + + @Override + @Deprecated + public final void setDeviceOwnerProtectedPackages( + String deviceOwnerPackageName, List<String> packageNames) { + getProtectedPackages().setDeviceOwnerProtectedPackages( + deviceOwnerPackageName, packageNames); + } + + @Override + @Deprecated + public final boolean isPackageDataProtected(int userId, String packageName) { + return getProtectedPackages().isPackageDataProtected(userId, packageName); + } + + @Override + @Deprecated + public final boolean isPackageStateProtected(String packageName, int userId) { + return getProtectedPackages().isPackageStateProtected(userId, packageName); + } + + @Override + @Deprecated + public final boolean isPackageEphemeral(int userId, String packageName) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + return packageState != null + && packageState.getUserStateOrDefault(userId).isInstantApp(); + } + + @Override + @Deprecated + public final boolean wasPackageEverLaunched(String packageName, int userId) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + if (packageState == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + return !packageState.getUserStateOrDefault(userId).isNotLaunched(); + } + + @Override + @Deprecated + public final boolean isEnabledAndMatches(ParsedMainComponent component, long flags, int userId) { + return PackageStateUtils.isEnabledAndMatches( + getPackageStateInternal(component.getPackageName()), component, flags, userId); + } + + @Override + @Deprecated + public final boolean userNeedsBadging(int userId) { + return getUserNeedsBadging().get(userId); + } + + @Override + @Deprecated + public final String getNameForUid(int uid) { + return snapshot().getNameForUid(uid); + } + + @Override + @Deprecated + public final void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, + Intent origIntent, String resolvedType, String callingPackage, + @Nullable String callingFeatureId, boolean isRequesterInstantApp, + Bundle verificationBundle, int userId) { + mService.requestInstantAppResolutionPhaseTwo(responseObj, origIntent, + resolvedType, callingPackage, callingFeatureId, isRequesterInstantApp, + verificationBundle, userId); + } + + @Override + @Deprecated + public final void grantImplicitAccess(int userId, Intent intent, + int recipientAppId, int visibleUid, boolean direct) { + grantImplicitAccess(userId, intent, recipientAppId, visibleUid, direct, + false /* retainOnUpdate */); + } + + @Override + @Deprecated + public final void grantImplicitAccess(int userId, Intent intent, + int recipientAppId, int visibleUid, boolean direct, boolean retainOnUpdate) { + mService.grantImplicitAccess(snapshot(), userId, intent, + recipientAppId, visibleUid, direct, retainOnUpdate); + } + + @Override + @Deprecated + public final boolean isInstantAppInstallerComponent(ComponentName component) { + final ActivityInfo instantAppInstallerActivity = mService.mInstantAppInstallerActivity; + return instantAppInstallerActivity != null + && instantAppInstallerActivity.getComponentName().equals(component); + } + + @Override + @Deprecated + public final void pruneInstantApps() { + getInstantAppRegistry().pruneInstantApps(snapshot()); + } + + @Override + @Deprecated + public final String getSetupWizardPackageName() { + return mService.mSetupWizardPackage; + } + + @Override + @Deprecated + public final ResolveInfo resolveIntent(Intent intent, String resolvedType, + @PackageManager.ResolveInfoFlagsBits long flags, + @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, + boolean resolveForStart, int filterCallingUid) { + return getResolveIntentHelper().resolveIntentInternal(snapshot(), + intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart, + filterCallingUid); + } + + @Override + @Deprecated + public final ResolveInfo resolveService(Intent intent, String resolvedType, + @PackageManager.ResolveInfoFlagsBits long flags, int userId, int callingUid) { + return getResolveIntentHelper().resolveServiceInternal(snapshot(), intent, + resolvedType, flags, userId, callingUid); + } + + @Override + @Deprecated + public final ProviderInfo resolveContentProvider(String name, + @PackageManager.ResolveInfoFlagsBits long flags, int userId, int callingUid) { + return snapshot().resolveContentProvider(name, flags, userId,callingUid); + } + + @Override + @Deprecated + public final int getUidTargetSdkVersion(int uid) { + return snapshot().getUidTargetSdkVersion(uid); + } + + @Override + @Deprecated + public final int getPackageTargetSdkVersion(String packageName) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + if (packageState != null && packageState.getPkg() != null) { + return packageState.getPkg().getTargetSdkVersion(); + } + return Build.VERSION_CODES.CUR_DEVELOPMENT; + } + + @Override + @Deprecated + public final boolean canAccessInstantApps(int callingUid, @UserIdInt int userId) { + return snapshot().canViewInstantApps(callingUid, userId); + } + + @Override + @Deprecated + public final boolean canAccessComponent(int callingUid, @NonNull ComponentName component, + @UserIdInt int userId) { + return snapshot().canAccessComponent(callingUid, component, userId); + } + + @Override + @Deprecated + public final boolean hasInstantApplicationMetadata(String packageName, int userId) { + return getInstantAppRegistry().hasInstantApplicationMetadata(packageName, userId); + } + + @Override + @Deprecated + public final SparseArray<String> getAppsWithSharedUserIds() { + return snapshot().getAppsWithSharedUserIds(); + } + + @Override + @NonNull + @Deprecated + public final String[] getSharedUserPackagesForPackage(String packageName, int userId) { + return snapshot().getSharedUserPackagesForPackage(packageName, userId); + } + + @Override + @Deprecated + public final ArrayMap<String, ProcessInfo> getProcessesForUid(int uid) { + return snapshot().getProcessesForUid(uid); + } + + @Override + @Deprecated + public final int[] getPermissionGids(String permissionName, int userId) { + return getPermissionManager().getPermissionGids(permissionName, userId); + } + + @Override + @Deprecated + public final boolean isOnlyCoreApps() { + return mService.isOnlyCoreApps(); + } + + @Override + @Deprecated + public final void freeStorage(String volumeUuid, long bytes, + @StorageManager.AllocateFlags int flags) throws IOException { + mService.freeStorage(volumeUuid, bytes, flags); + } + + @Override + @Deprecated + public final void freeAllAppCacheAboveQuota(@NonNull String volumeUuid) throws IOException { + mService.freeAllAppCacheAboveQuota(volumeUuid); + } + + @Override + @Deprecated + public final void forEachPackageSetting(Consumer<PackageSetting> actionLocked) { + mService.forEachPackageSetting(actionLocked); + } + + @Override + @Deprecated + public final void forEachPackageState(Consumer<PackageStateInternal> action) { + mService.forEachPackageState(snapshot(), action); + } + + @Override + @Deprecated + public final void forEachPackage(Consumer<AndroidPackage> action) { + mService.forEachPackage(snapshot(), action); + } + + @Override + @Deprecated + public final void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> action, + @UserIdInt int userId) { + mService.forEachInstalledPackage(snapshot(), action, userId); + } + + @Override + @Deprecated + public final ArraySet<String> getEnabledComponents(String packageName, int userId) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + if (packageState == null) { + return new ArraySet<>(); + } + return packageState.getUserStateOrDefault(userId).getEnabledComponents(); + } + + @Override + @Deprecated + public final ArraySet<String> getDisabledComponents(String packageName, int userId) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + if (packageState == null) { + return new ArraySet<>(); + } + return packageState.getUserStateOrDefault(userId).getDisabledComponents(); + } + + @Override + @Deprecated + public final @PackageManager.EnabledState int getApplicationEnabledState( + String packageName, int userId) { + final PackageStateInternal packageState = getPackageStateInternal(packageName); + if (packageState == null) { + return COMPONENT_ENABLED_STATE_DEFAULT; + } + return packageState.getUserStateOrDefault(userId).getEnabledState(); + } + + @Override + @Deprecated + public final @PackageManager.EnabledState int getComponentEnabledSetting( + @NonNull ComponentName componentName, int callingUid, int userId) { + return snapshot().getComponentEnabledSettingInternal( + componentName, callingUid, userId); + } + + @Override + @Deprecated + public final void setEnableRollbackCode(int token, int enableRollbackCode) { + mService.setEnableRollbackCode(token, enableRollbackCode); + } + + @Override + @Deprecated + public final void finishPackageInstall(int token, boolean didLaunch) { + mService.finishPackageInstall(token, didLaunch); + } + + @Override + @Deprecated + public final boolean isApexPackage(String packageName) { + return getApexManager().isApexPackage(packageName); + } + + @Override + @Deprecated + public final List<String> getApksInApex(String apexPackageName) { + return getApexManager().getApksInApex(apexPackageName); + } + + @Override + @Deprecated + public final boolean isCallerInstallerOfRecord(@NonNull AndroidPackage pkg, int callingUid) { + return snapshot().isCallerInstallerOfRecord(pkg, callingUid); + } + + @Override + @Deprecated + public final List<String> getMimeGroup(String packageName, String mimeGroup) { + return mService.getMimeGroupInternal(snapshot(), packageName, mimeGroup); + } + + @Override + @Deprecated + public final boolean isSystemPackage(@NonNull String packageName) { + return packageName.equals(mService.ensureSystemPackageName(snapshot(), packageName)); + } + + @Override + @Deprecated + public final void unsuspendForSuspendingPackage(final String packageName, int affectedUser) { + mService.unsuspendForSuspendingPackage(snapshot(), packageName, affectedUser); + } + + @Override + @Deprecated + public final boolean isSuspendingAnyPackages(String suspendingPackage, int userId) { + return snapshot().isSuspendingAnyPackages(suspendingPackage, userId); + } + + @Override + @Deprecated + public final void requestChecksums(@NonNull String packageName, boolean includeSplits, + @Checksum.TypeMask int optional, @Checksum.TypeMask int required, + @Nullable List trustedInstallers, + @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, + @NonNull Executor executor, @NonNull Handler handler) { + mService.requestChecksumsInternal(snapshot(), packageName, includeSplits, optional, + required, trustedInstallers, onChecksumsReadyListener, userId, executor, + handler); + } + + @Override + @Deprecated + public final boolean isPackageFrozen(@NonNull String packageName, + int callingUid, int userId) { + return snapshot().getPackageStartability(mService.getSafeMode(), packageName, callingUid, userId) + == PackageManagerService.PACKAGE_STARTABILITY_FROZEN; + } + + @Override + @Deprecated + public final long deleteOatArtifactsOfPackage(String packageName) { + return mService.deleteOatArtifactsOfPackage(snapshot(), packageName); + } + + @Override + @Deprecated + public final void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags, + boolean migrateAppsData) { + getAppDataHelper().reconcileAppsData(userId, flags, migrateAppsData); + } + + @Override + @NonNull + public ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId) { + return snapshot().getSharedUserPackages(sharedUserAppId); + } + + @Override + @Nullable + public SharedUserApi getSharedUserApi(int sharedUserAppId) { + return snapshot().getSharedUser(sharedUserAppId); + } + + @NonNull + @Override + @Deprecated + public final PackageStateMutator.InitialState recordInitialState() { + return mService.recordInitialState(); + } + + @Nullable + @Override + @Deprecated + public final PackageStateMutator.Result commitPackageStateMutation( + @Nullable PackageStateMutator.InitialState state, + @NonNull Consumer<PackageStateMutator> consumer) { + return mService.commitPackageStateMutation(state, consumer); + } + + @Override + @Deprecated + public final void shutdown() { + mService.shutdown(); + } + + @Override + @Deprecated + public final DynamicCodeLogger getDynamicCodeLogger() { + return getDexManager().getDynamicCodeLogger(); + } +} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e20a861e2eae..99c9c689544d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -29,7 +29,6 @@ import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.content.pm.PackageManager.RESTRICTION_NONE; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.os.storage.StorageManager.FLAG_STORAGE_CE; import static android.os.storage.StorageManager.FLAG_STORAGE_DE; @@ -83,21 +82,15 @@ import android.content.pm.IDexModuleRegisterCallback; import android.content.pm.IOnChecksumsReadyListener; import android.content.pm.IPackageChangeObserver; import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageInstallObserver2; -import android.content.pm.IPackageInstaller; import android.content.pm.IPackageLoadingProgressCallback; import android.content.pm.IPackageManager; import android.content.pm.IPackageMoveObserver; -import android.content.pm.IPackageStatsObserver; import android.content.pm.IncrementalStatesInfo; import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppInfo; import android.content.pm.InstantAppRequest; -import android.content.pm.InstrumentationInfo; -import android.content.pm.IntentFilterVerificationInfo; -import android.content.pm.KeySet; import android.content.pm.ModuleInfo; import android.content.pm.PackageChangeEvent; import android.content.pm.PackageInfo; @@ -109,11 +102,8 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.PackagePartitions; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.content.pm.ProcessInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; import android.content.pm.SigningDetails; @@ -122,7 +112,6 @@ import android.content.pm.TestUtilityService; import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VersionedPackage; -import android.content.pm.dex.IArtManager; import android.content.pm.overlay.OverlayPaths; import android.content.pm.parsing.PackageLite; import android.content.res.Resources; @@ -213,7 +202,6 @@ import com.android.server.pm.Settings.VersionInfo; import com.android.server.pm.dex.ArtManagerService; import com.android.server.pm.dex.ArtUtils; import com.android.server.pm.dex.DexManager; -import com.android.server.pm.dex.DynamicCodeLogger; import com.android.server.pm.dex.ViewCompiler; import com.android.server.pm.parsing.PackageCacher; import com.android.server.pm.parsing.PackageInfoUtils; @@ -225,10 +213,7 @@ import com.android.server.pm.permission.LegacyPermissionManagerInternal; import com.android.server.pm.permission.LegacyPermissionManagerService; import com.android.server.pm.permission.PermissionManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; -import com.android.server.pm.pkg.AndroidPackageApi; -import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateInternal; -import com.android.server.pm.pkg.PackageStateUtils; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.SharedUserApi; @@ -413,7 +398,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService public @interface ScanFlags {} /** - * Used as the result code of the {@link #getPackageStartability}. + * Used as the result code of the {@link Computer#getPackageStartability(boolean, String, int, + * int)}. */ @IntDef(value = { PACKAGE_STARTABILITY_OK, @@ -426,40 +412,43 @@ public class PackageManagerService implements PackageSender, TestUtilityService public @interface PackageStartability {} /** - * Used as the result code of the {@link #getPackageStartability} to indicate - * the given package is allowed to start. + * Used as the result code of the {@link Computer#getPackageStartability(boolean, String, int, + * int)} to indicate the given package is allowed to start. */ public static final int PACKAGE_STARTABILITY_OK = 0; /** - * Used as the result code of the {@link #getPackageStartability} to indicate - * the given package is <b>not</b> allowed to start because it's not found + * Used as the result code of the {@link Computer#getPackageStartability(boolean, String, int, + * int)} to indicate the given package is <b>not</b> allowed to start because it's not found * (could be due to that package is invisible to the given user). */ public static final int PACKAGE_STARTABILITY_NOT_FOUND = 1; /** - * Used as the result code of the {@link #getPackageStartability} to indicate - * the given package is <b>not</b> allowed to start because it's not a system app - * and the system is running in safe mode. + * Used as the result code of the {@link Computer#getPackageStartability(boolean, String, int, + * int)} to indicate the given package is <b>not</b> allowed to start because it's not a system + * app and the system is running in safe mode. */ public static final int PACKAGE_STARTABILITY_NOT_SYSTEM = 2; /** - * Used as the result code of the {@link #getPackageStartability} to indicate - * the given package is <b>not</b> allowed to start because it's currently frozen. + * Used as the result code of the {@link Computer#getPackageStartability(boolean, String, int, + * int)} to indicate the given package is <b>not</b> allowed to start because it's currently + * frozen. */ public static final int PACKAGE_STARTABILITY_FROZEN = 3; /** - * Used as the result code of the {@link #getPackageStartability} to indicate - * the given package is <b>not</b> allowed to start because it doesn't support + * Used as the result code of the {@link Computer#getPackageStartability(boolean, String, int, + * int)} to indicate the given package is <b>not</b> allowed to start because it doesn't support * direct boot. */ public static final int PACKAGE_STARTABILITY_DIRECT_BOOT_UNSUPPORTED = 4; private static final String STATIC_SHARED_LIB_DELIMITER = "_"; - /** Extension of the compressed packages */ + /** + * Extension of the compressed packages + */ public final static String COMPRESSED_EXTENSION = ".gz"; /** Suffix of stub packages on the system partition */ public final static String STUB_SUFFIX = "-Stub"; @@ -644,9 +633,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService */ boolean mPromoteSystemApps; - // TODO: Make IPackageManager reference private to hide discouraged APIs - final IPackageManagerImpl mIPackageManager; - private final PackageManagerInternal mPmInternal; private final TestUtilityService mTestUtilityService; @Watched @@ -1057,9 +1043,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService // A lock-free cache for frequently called functions. private volatile Computer mSnapshotComputer; - // A trampoline that directs callers to either the live or snapshot computer. - final ComputerTracker mComputer = new ComputerTracker(this); - // If true, the snapshot is invalid (stale). The attribute is static since it may be // set from outside classes. The attribute may be set to true anywhere, although it // should only be set true while holding mLock. However, the attribute id guaranteed @@ -1088,6 +1071,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService * Return the cached computer. The method will rebuild the cached computer if necessary. * The live computer will be returned if snapshots are disabled. */ + @VisibleForTesting(visibility = Visibility.PACKAGE) + @NonNull public Computer snapshotComputer() { if (Thread.holdsLock(mLock)) { // If the current thread holds mLock then it may have modified state but not @@ -1247,15 +1232,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService ApkChecksums.Injector injector = new ApkChecksums.Injector( () -> mContext, () -> handler, - () -> mInjector.getIncrementalManager(), - () -> mPmInternal); + mInjector::getIncrementalManager, + () -> mInjector.getLocalService(PackageManagerInternal.class)); ApkChecksums.getChecksums(filesToChecksum, optional, required, installerPackageName, trustedCerts, onChecksumsReadyListener, injector); }); } - private void requestChecksumsInternal(@NonNull String packageName, boolean includeSplits, - @Checksum.TypeMask int optional, @Checksum.TypeMask int required, + void requestChecksumsInternal(@NonNull Computer snapshot, @NonNull String packageName, + boolean includeSplits, @Checksum.TypeMask int optional, @Checksum.TypeMask int required, @Nullable List trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, @NonNull Executor executor, @NonNull Handler handler) { @@ -1264,13 +1249,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService Objects.requireNonNull(executor); Objects.requireNonNull(handler); - final ApplicationInfo applicationInfo = getApplicationInfoInternal(packageName, 0, + final ApplicationInfo applicationInfo = snapshot.getApplicationInfoInternal(packageName, 0, Binder.getCallingUid(), userId); if (applicationInfo == null) { throw new ParcelableException(new PackageManager.NameNotFoundException(packageName)); } - final InstallSourceInfo installSourceInfo = - mIPackageManager.getInstallSourceInfo(packageName); + final InstallSourceInfo installSourceInfo = snapshot.getInstallSourceInfo(packageName); final String installerPackageName = installSourceInfo != null ? installSourceInfo.getInitiatingPackageName() : null; @@ -1294,8 +1278,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService ApkChecksums.Injector injector = new ApkChecksums.Injector( () -> mContext, () -> handler, - () -> mInjector.getIncrementalManager(), - () -> mPmInternal); + mInjector::getIncrementalManager, + () -> mInjector.getLocalService(PackageManagerInternal.class)); ApkChecksums.getChecksums(filesToChecksum, optional, required, installerPackageName, trustedCerts, onChecksumsReadyListener, injector); }); @@ -1440,15 +1424,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService RuntimePermissionsPersistence.createInstance(), i.getPermissionManagerServiceInternal(), domainVerificationService, lock), - (i, pm) -> AppsFilter.create(pm.mPmInternal, i), + (i, pm) -> AppsFilter.create(i, i.getLocalService(PackageManagerInternal.class)), (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"), (i, pm) -> SystemConfig.getInstance(), (i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(), i.getContext(), "*dexopt*"), - (i, pm) -> new DexManager(i.getContext(), pm.mIPackageManager, - i.getPackageDexOptimizer(), i.getInstaller(), i.getInstallLock()), - (i, pm) -> new ArtManagerService(i.getContext(), pm.mIPackageManager, + (i, pm) -> new DexManager(i.getContext(), i.getPackageDexOptimizer(), i.getInstaller(), i.getInstallLock()), + (i, pm) -> new ArtManagerService(i.getContext(), i.getInstaller(), + i.getInstallLock()), (i, pm) -> ApexManager.getInstance(), (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()), (i, pm) -> (IncrementalManager) @@ -1470,7 +1454,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService i.getContext(), pm, i::getScanningPackageParser), (i, pm, cn) -> new InstantAppResolverConnection( i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE), - (i, pm) -> new ModuleInfoProvider(i.getContext(), pm.mIPackageManager), + (i, pm) -> new ModuleInfoProvider(i.getContext()), (i, pm) -> LegacyPermissionManagerService.create(i.getContext()), (i, pm) -> domainVerificationService, (i, pm) -> { @@ -1498,13 +1482,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService final CompatChange.ChangeListener selinuxChangeListener = packageName -> { synchronized (m.mInstallLock) { - final PackageStateInternal packageState = m.getPackageStateInternal(packageName); + final Computer snapshot = m.snapshotComputer(); + final PackageStateInternal packageState = + snapshot.getPackageStateInternal(packageName); if (packageState == null) { Slog.e(TAG, "Failed to find package setting " + packageName); return; } AndroidPackage pkg = packageState.getPkg(); - SharedUserApi sharedUser = m.mComputer.getSharedUser( + SharedUserApi sharedUser = snapshot.getSharedUser( packageState.getSharedUserAppId()); String oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, packageState); @@ -1531,11 +1517,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService selinuxChangeListener); m.installAllowlistedSystemPackages(); - ServiceManager.addService("package", m.mIPackageManager); + IPackageManagerImpl iPackageManager = m.new IPackageManagerImpl(); + ServiceManager.addService("package", iPackageManager); final PackageManagerNative pmn = new PackageManagerNative(m); ServiceManager.addService("package_native", pmn); LocalManagerRegistry.addManager(PackageManagerLocal.class, m.new PackageManagerLocalImpl()); - return Pair.create(m, m.mIPackageManager); + return Pair.create(m, iPackageManager); } /** Install/uninstall system packages for all users based on their user-type, as applicable. */ @@ -1641,8 +1628,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mPackageDexOptimizer = testParams.packageDexOptimizer; mPackageParserCallback = testParams.packageParserCallback; mPendingBroadcasts = testParams.pendingPackageBroadcasts; - mIPackageManager = new IPackageManagerImpl(); - mPmInternal = testParams.pmInternal; mTestUtilityService = testParams.testUtilityService; mProcessLoggingHandler = testParams.processLoggingHandler; mProtectedPackages = testParams.protectedPackages; @@ -1703,7 +1688,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService public PackageManagerService(PackageManagerServiceInjector injector, boolean onlyCore, boolean factoryTest, final String buildFingerprint, final boolean isEngBuild, final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) { - mIPackageManager = new IPackageManagerImpl(); mIsEngBuild = isEngBuild; mIsUserDebugBuild = isUserDebugBuild; mSdkVersion = sdkVersion; @@ -1734,10 +1718,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService t.traceBegin("createSubComponents"); // Expose private service for system components to use. - mPmInternal = new PackageManagerInternalImpl(); + LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl()); LocalServices.addService(TestUtilityService.class, this); mTestUtilityService = LocalServices.getService(TestUtilityService.class); - LocalServices.addService(PackageManagerInternal.class, mPmInternal); mUserManager = injector.getUserManagerService(); mUserNeedsBadging = new UserNeedsBadgingCache(mUserManager); mComponentResolver = injector.getComponentResolver(); @@ -1755,7 +1738,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public boolean hasFeature(String feature) { - return PackageManagerService.this.mIPackageManager.hasSystemFeature(feature, 0); + return PackageManagerService.this.hasSystemFeature(feature, 0); } }; @@ -1885,9 +1868,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService final int dependencyCount = entry.dependencies.length; for (int j = 0; j < dependencyCount; j++) { final SharedLibraryInfo dependency = - getSharedLibraryInfo(entry.dependencies[j], undefinedVersion); + computer.getSharedLibraryInfo(entry.dependencies[j], undefinedVersion); if (dependency != null) { - getSharedLibraryInfo(name, undefinedVersion).addDependency(dependency); + computer.getSharedLibraryInfo(name, undefinedVersion) + .addDependency(dependency); } } } @@ -1899,7 +1883,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService t.traceEnd(); t.traceBegin("read user settings"); - mFirstBoot = !mSettings.readLPw(mLiveComputer, + mFirstBoot = !mSettings.readLPw(computer, mInjector.getUserManagerInternal().getUsers( /* excludePartial= */ true, /* excludeDying= */ false, @@ -1980,19 +1964,26 @@ public class PackageManagerService implements PackageSender, TestUtilityService // Resolve protected action filters. Only the setup wizard is allowed to // have a high priority filter for these actions. mSetupWizardPackage = getSetupWizardPackageNameImpl(computer); - mComponentResolver.fixProtectedFilterPriorities(mPmInternal.getSetupWizardPackageName()); - - mDefaultTextClassifierPackage = mIPackageManager.getDefaultTextClassifierPackageName(); - mSystemTextClassifierPackageName = - mIPackageManager.getSystemTextClassifierPackageName(); - mConfiguratorPackage = getDeviceConfiguratorPackageName(); - mAppPredictionServicePackage = mIPackageManager.getAppPredictionServicePackageName(); - mIncidentReportApproverPackage = - mIPackageManager.getIncidentReportApproverPackageName(); + mComponentResolver.fixProtectedFilterPriorities(mSetupWizardPackage); + + mDefaultTextClassifierPackage = ensureSystemPackageName(computer, + mContext.getString(R.string.config_servicesExtensionPackage)); + mSystemTextClassifierPackageName = ensureSystemPackageName(computer, + mContext.getString(R.string.config_defaultTextClassifierPackage)); + mConfiguratorPackage = ensureSystemPackageName(computer, + mContext.getString(R.string.config_deviceConfiguratorPackageName)); + mAppPredictionServicePackage = ensureSystemPackageName(computer, + getPackageFromComponentString(R.string.config_defaultAppPredictionService)); + mIncidentReportApproverPackage = ensureSystemPackageName(computer, + mContext.getString(R.string.config_incidentReportApproverPackage)); mRetailDemoPackage = getRetailDemoPackageName(); - mOverlayConfigSignaturePackage = getOverlayConfigSignaturePackageName(); - mRecentsPackage = getRecentsPackageName(); - mAmbientContextDetectionPackage = getAmbientContextDetectionPackageName(); + mOverlayConfigSignaturePackage = ensureSystemPackageName(computer, + mInjector.getSystemConfig().getOverlayConfigSignaturePackage()); + mRecentsPackage = ensureSystemPackageName(computer, + getPackageFromComponentString(R.string.config_recentsComponentName)); + mAmbientContextDetectionPackage = ensureSystemPackageName(computer, + getPackageFromComponentString( + R.string.config_defaultAmbientContextDetectionService)); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. @@ -2126,8 +2117,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDomainVerificationManager.setProxy(domainVerificationProxy); - mServicesExtensionPackageName = getRequiredServicesExtensionPackageLPr(); - mSharedSystemSharedLibraryPackageName = getRequiredSharedLibrary( + mServicesExtensionPackageName = getRequiredServicesExtensionPackageLPr(computer); + mSharedSystemSharedLibraryPackageName = getRequiredSharedLibrary(computer, PackageManager.SYSTEM_SHARED_LIBRARY_SHARED, SharedLibraryInfo.VERSION_UNDEFINED); } else { @@ -2143,11 +2134,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(computer); mSettings.setPermissionControllerVersion( - mIPackageManager.getPackageInfo(mRequiredPermissionControllerPackage, 0, + computer.getPackageInfo(mRequiredPermissionControllerPackage, 0, UserHandle.USER_SYSTEM).getLongVersionCode()); // Resolve the sdk sandbox package - mRequiredSdkSandboxPackage = getRequiredSdkSandboxPackageName(); + mRequiredSdkSandboxPackage = getRequiredSdkSandboxPackageName(computer); // Initialize InstantAppRegistry's Instant App list for all users. for (AndroidPackage pkg : mPackages.values()) { @@ -2155,7 +2146,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService continue; } for (int userId : userIds) { - final PackageStateInternal ps = getPackageStateInternal(pkg.getPackageName()); + final PackageStateInternal ps = + computer.getPackageStateInternal(pkg.getPackageName()); if (ps == null || !ps.getUserStateOrDefault(userId).isInstantApp() || !ps.getUserStateOrDefault(userId).isInstalled()) { continue; @@ -2165,7 +2157,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } mInstallerService = mInjector.getPackageInstallerService(); - final ComponentName instantAppResolverComponent = getInstantAppResolver(); + final ComponentName instantAppResolverComponent = getInstantAppResolver(computer); if (instantAppResolverComponent != null) { if (DEBUG_INSTANT) { Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent); @@ -2191,7 +2183,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService // scanning). final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>(); for (int userId : userIds) { - userPackages.put(userId, mIPackageManager.getInstalledPackages(/*flags*/ 0, userId) + userPackages.put(userId, computer.getInstalledPackages(/*flags*/ 0, userId) .getList()); } mDexManager.load(userPackages); @@ -2202,7 +2194,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService SystemClock.uptimeMillis() - startTime); } - // Rebild the live computer since some attributes have been rebuilt. + // Rebuild the live computer since some attributes have been rebuilt. mLiveComputer = createLiveComputer(); } // synchronized (mLock) @@ -2210,6 +2202,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService // CHECKSTYLE:ON IndentationCheck mModuleInfoProvider = mInjector.getModuleInfoProvider(); + mInjector.getSystemWrapper().enablePackageCaches(); // Now after opening every single application zip, make sure they @@ -2281,8 +2274,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @NonNull - private String getRequiredSharedLibrary(@NonNull String name, int version) { - SharedLibraryInfo libraryInfo = getSharedLibraryInfo(name, version); + private String getRequiredSharedLibrary(@NonNull Computer snapshot, @NonNull String name, + int version) { + SharedLibraryInfo libraryInfo = snapshot.getSharedLibraryInfo(name, version); if (libraryInfo == null) { throw new IllegalStateException("Missing required shared library:" + name); } @@ -2294,9 +2288,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @NonNull - private String getRequiredServicesExtensionPackageLPr() { + private String getRequiredServicesExtensionPackageLPr(@NonNull Computer computer) { String servicesExtensionPackage = - ensureSystemPackageName( + ensureSystemPackageName(computer, mContext.getString(R.string.config_servicesExtensionPackage)); if (TextUtils.isEmpty(servicesExtensionPackage)) { throw new RuntimeException( @@ -2375,7 +2369,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService for (int i = 0; i < N; i++) { final ResolveInfo cur = matches.get(i); final String packageName = cur.getComponentInfo().packageName; - if (mIPackageManager.checkPermission( + if (checkPermission( android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT, packageName, UserHandle.USER_SYSTEM) != PackageManager.PERMISSION_GRANTED) { continue; @@ -2405,7 +2399,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService for (int i = 0; i < N; i++) { final ResolveInfo cur = matches.get(i); final String packageName = cur.getComponentInfo().packageName; - if (mIPackageManager.checkPermission( + if (checkPermission( android.Manifest.permission.DOMAIN_VERIFICATION_AGENT, packageName, UserHandle.USER_SYSTEM) != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Domain verification agent found but does not hold permission: " @@ -2414,7 +2408,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } if (best == null || cur.priority > best.priority) { - if (mComputer.isComponentEffectivelyEnabled(cur.getComponentInfo(), + if (computer.isComponentEffectivelyEnabled(cur.getComponentInfo(), UserHandle.USER_SYSTEM)) { best = cur; } else { @@ -2430,7 +2424,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService return null; } - private @Nullable ComponentName getInstantAppResolver() { + @Nullable ComponentName getInstantAppResolver(@NonNull Computer snapshot) { final String[] packageArray = mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage); if (packageArray.length == 0 && !Build.IS_DEBUGGABLE) { @@ -2446,7 +2440,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService | MATCH_DIRECT_BOOT_UNAWARE | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0); final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE); - List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null, + List<ResolveInfo> resolvers = snapshot.queryIntentServicesInternal(resolverIntent, null, resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/); final int N = resolvers.size(); if (N == 0) { @@ -2519,7 +2513,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService Iterator<ResolveInfo> iter = matches.iterator(); while (iter.hasNext()) { final ResolveInfo rInfo = iter.next(); - if (mIPackageManager.checkPermission( + if (checkPermission( Manifest.permission.INSTALL_PACKAGES, rInfo.activityInfo.packageName, 0) == PERMISSION_GRANTED || mIsEngBuild) { continue; @@ -2550,48 +2544,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return matches.get(0).getComponentInfo().getComponentName(); } - /** - * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int) - */ - boolean shouldFilterApplication( - @Nullable PackageStateInternal ps, int callingUid, int userId) { - return mComputer.shouldFilterApplication( - ps, callingUid, userId); - } - - private @PackageStartability int getPackageStartability(String packageName, - int callingUid, int userId) { - return mComputer.getPackageStartability(mSafeMode, packageName, callingUid, userId); - } - - /** - * Returns whether or not a full application can see an instant application. - * <p> - * Currently, there are four cases in which this can occur: - * <ol> - * <li>The calling application is a "special" process. Special processes - * are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li> - * <li>The calling application has the permission - * {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li> - * <li>The calling application is the default launcher on the - * system partition.</li> - * <li>The calling application is the default app prediction service.</li> - * </ol> - */ - boolean canViewInstantApps(int callingUid, int userId) { - return mComputer.canViewInstantApps(callingUid, userId); - } - - private PackageInfo generatePackageInfo(@NonNull PackageStateInternal ps, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - return mComputer.generatePackageInfo(ps, flags, userId); - } - - int getPackageUidInternal(String packageName, - @PackageManager.PackageInfoFlagsBits long flags, int userId, int callingUid) { - return mComputer.getPackageUidInternal(packageName, flags, userId, callingUid); - } - public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) { // Because this is accessed via the package manager service AIDL, // go through the permission manager service AIDL @@ -2600,19 +2552,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } /** - * Important: The provided filterCallingUid is used exclusively to filter out applications - * that can be seen based on user state. It's typically the original caller uid prior - * to clearing. Because it can only be provided by trusted code, its value can be - * trusted and will be used as-is; unlike userId which will be validated by this method. - */ - private ApplicationInfo getApplicationInfoInternal(String packageName, - @PackageManager.ApplicationInfoFlagsBits long flags, - int filterCallingUid, int userId) { - return mComputer.getApplicationInfoInternal(packageName, flags, - filterCallingUid, userId); - } - - /** * Blocking call to clear all cached app data above quota. */ public void freeAllAppCacheAboveQuota(String volumeUuid) throws IOException { @@ -2648,7 +2587,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService // 2. Consider preloaded data (after 1w honeymoon, unless aggressive) if (internalVolume && (aggressive || SystemProperties .getBoolean("persist.sys.preloads.file_cache_expired", false))) { - mIPackageManager.deletePreloadsFileCache(); + deletePreloadsFileCache(); if (file.getUsableSpace() >= bytes) return; } @@ -2769,43 +2708,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return recommendedInstallLocation; } - /** - * Update given flags when being used to request {@link ResolveInfo}. - * <p>Instant apps are resolved specially, depending upon context. Minimally, - * {@code}flags{@code} must have the {@link PackageManager#MATCH_INSTANT} - * flag set. However, this flag is only honoured in three circumstances: - * <ul> - * <li>when called from a system process</li> - * <li>when the caller holds the permission {@code android.permission.ACCESS_INSTANT_APPS}</li> - * <li>when resolution occurs to start an activity with a {@code android.intent.action.VIEW} - * action and a {@code android.intent.category.BROWSABLE} category</li> - * </ul> - */ - long updateFlagsForResolve(long flags, int userId, int callingUid, - boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc) { - return mComputer.updateFlagsForResolve(flags, userId, callingUid, - wantInstantApps, isImplicitImageCaptureIntentAndNotSetByDpc); - } - - /** - * Important: The provided filterCallingUid is used exclusively to filter out activities - * that can be seen based on user state. It's typically the original caller uid prior - * to clearing. Because it can only be provided by trusted code, its value can be - * trusted and will be used as-is; unlike userId which will be validated by this method. - */ - private ActivityInfo getActivityInfoInternal(ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, int filterCallingUid, int userId) { - return mComputer.getActivityInfoInternal(component, flags, - filterCallingUid, userId); - } - - @Nullable - List<VersionedPackage> getPackagesUsingSharedLibrary( - SharedLibraryInfo libInfo, @PackageManager.PackageInfoFlagsBits long flags, - int callingUid, int userId) { - return mComputer.getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId); - } - public ModuleInfo getModuleInfo(String packageName, @PackageManager.ModuleInfoFlags int flags) { return mModuleInfoProvider.getModuleInfo(packageName, flags); } @@ -2840,7 +2742,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mRequiredInstallerPackage; } - private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, + void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, @Nullable String callingFeatureId, boolean isRequesterInstantApp, Bundle verificationBundle, int userId) { @@ -2852,31 +2754,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mHandler.sendMessage(msg); } - /** - * From Android R, camera intents have to match system apps. The only exception to this is if - * the DPC has set the camera persistent preferred activity. This case was introduced - * because it is important that the DPC has the ability to set both system and non-system - * camera persistent preferred activities. - * - * @return {@code true} if the intent is a camera intent and the persistent preferred - * activity was not set by the DPC. - */ - @GuardedBy("mLock") - boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, int userId, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags) { - return mComputer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, - resolvedType, flags); - } - - @GuardedBy("mLock") - ResolveInfo findPersistentPreferredActivityLP(Intent intent, - String resolvedType, - @PackageManager.ResolveInfoFlagsBits long flags, List<ResolveInfo> query, boolean debug, - int userId) { - return mComputer.findPersistentPreferredActivityLP(intent, - resolvedType, flags, query, debug, userId); - } - // findPreferredActivityBody returns two items: a "things changed" flag and a // ResolveInfo, which is the preferred activity itself. static class FindPreferredActivityBodyResult { @@ -2884,24 +2761,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService ResolveInfo mPreferredResolveInfo; } - FindPreferredActivityBodyResult findPreferredActivityInternal( - Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - List<ResolveInfo> query, boolean always, - boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) { - return mComputer.findPreferredActivityInternal( - intent, resolvedType, flags, - query, always, - removeMatches, debug, userId, queryMayBeFiltered); - } - - /** - * Returns the package name of the calling Uid if it's an instant app. If it isn't - * instant, returns {@code null}. - */ - String getInstantAppPackageName(int callingUid) { - return mComputer.getInstantAppPackageName(callingUid); - } - public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(@NonNull Computer snapshot, Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId) { @@ -2909,24 +2768,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService snapshot, intent, resolvedType, flags, userId, Binder.getCallingUid())); } - @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId, - int callingUid, boolean includeInstantApps) { - return mComputer.queryIntentServicesInternal(intent, - resolvedType, flags, userId, callingUid, - includeInstantApps); - } - - private boolean isInstantAppInternal(String packageName, @UserIdInt int userId, - int callingUid) { - return mComputer.isInstantAppInternal(packageName, userId, - callingUid); - } - - boolean isCallerSameApp(String packageName, int uid) { - return mComputer.isCallerSameApp(packageName, uid); - } - public static void reportSettingsProblem(int priority, String msg) { logCriticalInfo(priority, msg); } @@ -2943,39 +2784,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return packageName + STATIC_SHARED_LIB_DELIMITER + libraryVersion; } - /** - * Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS - * or INTERACT_ACROSS_USERS_FULL permissions, if the {@code userId} is not for the caller. - * - * @param checkShell whether to prevent shell from access if there's a debugging restriction - * @param message the message to log on security exception - */ - void enforceCrossUserPermission(int callingUid, @UserIdInt int userId, - boolean requireFullPermission, boolean checkShell, String message) { - mComputer.enforceCrossUserPermission(callingUid, userId, - requireFullPermission, checkShell, message); - } - - /** - * Checks if the request is from the system or an app that has the appropriate cross-user - * permissions defined as follows: - * <ul> - * <li>INTERACT_ACROSS_USERS_FULL if {@code requireFullPermission} is true.</li> - * <li>INTERACT_ACROSS_USERS if the given {@code userId} is in a different profile group - * to the caller.</li> - * <li>Otherwise, INTERACT_ACROSS_PROFILES if the given {@code userId} is in the same profile - * group as the caller.</li> - * </ul> - * - * @param checkShell whether to prevent shell from access if there's a debugging restriction - * @param message the message to log on security exception - */ - private void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId, - boolean requireFullPermission, boolean checkShell, String message) { - mComputer.enforceCrossUserOrProfilePermission(callingUid, userId, - requireFullPermission, checkShell, message); - } - public void performFstrimIfNeeded() { PackageManagerServiceUtils.enforceSystemOrRoot("Only the system can request fstrim"); @@ -3033,17 +2841,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mDexManager; } - @NonNull - List<PackageStateInternal> findSharedNonSystemLibraries( - @NonNull PackageStateInternal pkgSetting) { - return mComputer.findSharedNonSystemLibraries(pkgSetting); - } - - @Nullable - SharedLibraryInfo getSharedLibraryInfo(String name, long version) { - return mComputer.getSharedLibraryInfo(name, version); - } - public void shutdown() { mCompilerStats.writeNow(); mDexManager.writePackageDexUsageNow(); @@ -3141,14 +2938,14 @@ public class PackageManagerService implements PackageSender, TestUtilityService mPackageObserverHelper.notifyRemoved(packageName, uid); } - void sendPackageAddedForUser(String packageName, @NonNull PackageStateInternal packageState, - int userId, int dataLoaderType) { + void sendPackageAddedForUser(@NonNull Computer snapshot, String packageName, + @NonNull PackageStateInternal packageState, int userId, 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(packageName, isSystem /*sendBootCompleted*/, + sendPackageAddedForNewUsers(snapshot, packageName, isSystem /*sendBootCompleted*/, false /*startReceiver*/, packageState.getAppId(), userIds, instantUserIds, dataLoaderType); @@ -3160,15 +2957,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted, - boolean includeStopped, @AppIdInt int appId, int[] userIds, int[] instantUserIds, - int dataLoaderType) { + public void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName, + boolean sendBootCompleted, boolean includeStopped, @AppIdInt int appId, int[] userIds, + int[] instantUserIds, int dataLoaderType) { if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) { return; } SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList( - getPackageStateInternal(packageName, Process.SYSTEM_UID), - userIds, getPackageStates()); + snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID), + userIds, snapshot.getPackageStates()); mHandler.post(() -> mBroadcastHelper.sendPackageAddedForNewUsers( packageName, appId, userIds, instantUserIds, dataLoaderType, broadcastAllowList)); if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) { @@ -3202,8 +2999,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService return false; } - private void enforceCanSetPackagesSuspendedAsUser(String callingPackage, int callingUid, - int userId, String callingMethod) { + private void enforceCanSetPackagesSuspendedAsUser(@NonNull Computer snapshot, + String callingPackage, int callingUid, int userId, String callingMethod) { if (callingUid == Process.ROOT_UID // Need to compare app-id to allow system dialogs access on secondary users || UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { @@ -3212,7 +3009,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService final String ownerPackage = mProtectedPackages.getDeviceOwnerOrProfileOwnerPackage(userId); if (ownerPackage != null) { - final int ownerUid = mIPackageManager.getPackageUid(ownerPackage, 0, userId); + final int ownerUid = snapshot.getPackageUid(ownerPackage, 0, userId); if (ownerUid == callingUid) { return; } @@ -3221,7 +3018,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS, callingMethod); - final int packageUid = mIPackageManager.getPackageUid(callingPackage, 0, userId); + final int packageUid = snapshot.getPackageUid(callingPackage, 0, userId); final boolean allowedPackageUid = packageUid == callingUid; // TODO(b/139383163): remove special casing for shell and enforce INTERACT_ACROSS_USERS_FULL final boolean allowedShell = callingUid == SHELL_UID @@ -3242,13 +3039,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService allPackages, suspendingPackage::equals, userId); } - private boolean isSuspendingAnyPackages(String suspendingPackage, int userId) { - return mComputer.isSuspendingAnyPackages(suspendingPackage, userId); - } - - void removeAllDistractingPackageRestrictions(int userId) { - final String[] allPackages = mComputer.getAllAvailablePackageNames(); - removeDistractingPackageRestrictions(allPackages, userId); + void removeAllDistractingPackageRestrictions(@NonNull Computer snapshot, int userId) { + final String[] allPackages = snapshot.getAllAvailablePackageNames(); + removeDistractingPackageRestrictions(snapshot, allPackages, userId); } /** @@ -3260,11 +3053,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService * @param packagesToChange The packages on which restrictions are to be removed. * @param userId the user for which changes are taking place. */ - private void removeDistractingPackageRestrictions(String[] packagesToChange, int userId) { + void removeDistractingPackageRestrictions(@NonNull Computer snapshot, + String[] packagesToChange, int userId) { final List<String> changedPackages = new ArrayList<>(); final IntArray changedUids = new IntArray(); for (String packageName : packagesToChange) { - final PackageStateInternal ps = getPackageStateInternal(packageName); + final PackageStateInternal ps = snapshot.getPackageStateInternal(packageName); if (ps != null && ps.getUserStateOrDefault(userId).getDistractionFlags() != 0) { changedPackages.add(ps.getPackageName()); changedUids.add(UserHandle.getUid(userId, ps.getAppId())); @@ -3287,7 +3081,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - private void setEnableRollbackCode(int token, int enableRollbackCode) { + void setEnableRollbackCode(int token, int enableRollbackCode) { final Message msg = mHandler.obtainMessage(ENABLE_ROLLBACK_STATUS); msg.arg1 = token; msg.arg2 = enableRollbackCode; @@ -3334,7 +3128,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService if (DEBUG_BACKUP) { Slog.i(TAG, "Package " + packageName + " sending normal FIRST_LAUNCH"); } - final boolean isInstantApp = isInstantAppInternal( + final boolean isInstantApp = snapshotComputer().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; @@ -3384,30 +3178,22 @@ public class PackageManagerService implements PackageSender, TestUtilityService versionedPackage, observer, userId, deleteFlags, false); } - private String resolveExternalPackageName(AndroidPackage pkg) { - return mComputer.resolveExternalPackageName(pkg); - } - - String resolveInternalPackageName(String packageName, long versionCode) { - return mComputer.resolveInternalPackageName(packageName, versionCode); - } - - boolean isCallerVerifier(int callingUid) { + boolean isCallerVerifier(@NonNull Computer snapshot, int callingUid) { final int callingUserId = UserHandle.getUserId(callingUid); - return mRequiredVerifierPackage != null && callingUid == mIPackageManager.getPackageUid( + return mRequiredVerifierPackage != null && callingUid == snapshot.getPackageUid( mRequiredVerifierPackage, 0, callingUserId); } - public boolean isPackageDeviceAdminOnAnyUser(String packageName) { + public boolean isPackageDeviceAdminOnAnyUser(@NonNull Computer snapshot, String packageName) { final int callingUid = Binder.getCallingUid(); - if (mIPackageManager.checkUidPermission(android.Manifest.permission.MANAGE_USERS, - callingUid) != PERMISSION_GRANTED) { + if (snapshot.checkUidPermission(android.Manifest.permission.MANAGE_USERS, callingUid) + != PERMISSION_GRANTED) { EventLog.writeEvent(0x534e4554, "128599183", -1, ""); throw new SecurityException(android.Manifest.permission.MANAGE_USERS + " permission is required to call this API"); } - if (getInstantAppPackageName(callingUid) != null - && !isCallerSameApp(packageName, callingUid)) { + if (snapshot.getInstantAppPackageName(callingUid) != null + && !snapshot.isCallerSameApp(packageName, callingUid)) { return false; } return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL); @@ -3456,14 +3242,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mDevicePolicyManager; } - private boolean clearApplicationUserDataLIF(String packageName, int userId) { + private boolean clearApplicationUserDataLIF(@NonNull Computer snapshot, String packageName, + int userId) { if (packageName == null) { Slog.w(TAG, "Attempt to delete null packageName."); return false; } // Try finding details about the requested package - AndroidPackage pkg = getPackage(packageName); + AndroidPackage pkg = snapshot.getPackage(packageName); if (pkg == null) { Slog.w(TAG, "Package named '" + packageName + "' doesn't exist."); return false; @@ -3486,8 +3273,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService } else { flags = 0; } - mAppDataHelper.prepareAppDataContentsLIF(pkg, getPackageStateInternal(packageName), userId, - flags); + mAppDataHelper.prepareAppDataContentsLIF(pkg, snapshot.getPackageStateInternal(packageName), + userId, flags); return true; } @@ -3538,10 +3325,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - int getUidTargetSdkVersion(int uid) { - return mComputer.getUidTargetSdkVersion(uid); - } - void postPreferredActivityChangedBroadcast(int userId) { mHandler.post(() -> mBroadcastHelper.sendPreferredActivityChangedBroadcast(userId)); } @@ -3562,18 +3345,19 @@ public class PackageManagerService implements PackageSender, TestUtilityService // Persistent preferred activity might have came into effect due to this // install. - mPreferredActivityHelper.updateDefaultHomeNotLocked(userId); + mPreferredActivityHelper.updateDefaultHomeNotLocked(snapshotComputer(), userId); } /** * Variant that takes a {@link WatchedIntentFilter} */ - public void addCrossProfileIntentFilter(WatchedIntentFilter intentFilter, String ownerPackage, - int sourceUserId, int targetUserId, int flags) { + public void addCrossProfileIntentFilter(@NonNull Computer snapshot, + WatchedIntentFilter intentFilter, String ownerPackage, int sourceUserId, + int targetUserId, int flags) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); int callingUid = Binder.getCallingUid(); - enforceOwnerRights(ownerPackage, callingUid); + enforceOwnerRights(snapshot, ownerPackage, callingUid); PackageManagerServiceUtils.enforceShellRestriction(mInjector.getUserManagerInternal(), UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId); if (intentFilter.countActions() == 0) { @@ -3601,18 +3385,18 @@ public class PackageManagerService implements PackageSender, TestUtilityService } // Enforcing that callingUid is owning pkg on userId - private void enforceOwnerRights(String pkg, int callingUid) { + private void enforceOwnerRights(@NonNull Computer snapshot, String pkg, int callingUid) { // The system owns everything. if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { return; } - final String[] callerPackageNames = mIPackageManager.getPackagesForUid(callingUid); + final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid); if (!ArrayUtils.contains(callerPackageNames, pkg)) { throw new SecurityException("Calling uid " + callingUid + " does not own package " + pkg); } final int callingUserId = UserHandle.getUserId(callingUid); - PackageInfo pi = mIPackageManager.getPackageInfo(pkg, 0, callingUserId); + PackageInfo pi = snapshot.getPackageInfo(pkg, 0, callingUserId); if (pi == null) { throw new IllegalArgumentException("Unknown package " + pkg + " on user " + callingUserId); @@ -3626,29 +3410,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService } final UserInfo parent = ums.getProfileParent(userId); final int launcherUid = (parent != null) ? parent.id : userId; - final ComponentName launcherComponent = getDefaultHomeActivity(launcherUid); + // TODO: Should this snapshot be moved further up? + final ComponentName launcherComponent = snapshotComputer() + .getDefaultHomeActivity(launcherUid); mBroadcastHelper.sendSessionCommitBroadcast(sessionInfo, userId, launcherUid, launcherComponent, mAppPredictionServicePackage); } - /** - * Report the 'Home' activity which is currently set as "always use this one". If non is set - * then reports the most likely home activity or null if there are more than one. - */ - private ComponentName getDefaultHomeActivity(int userId) { - return mComputer.getDefaultHomeActivity(userId); - } - - Intent getHomeIntent() { - return mComputer.getHomeIntent(); - } - - ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, - int userId) { - return mComputer.getHomeActivitiesAsUser(allHomeCandidates, - userId); - } - private @Nullable String getSetupWizardPackageNameImpl(@NonNull Computer computer) { final Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_SETUP_WIZARD); @@ -3682,10 +3450,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - private @NonNull String getRequiredSdkSandboxPackageName() { + @NonNull + private static String getRequiredSdkSandboxPackageName(@NonNull Computer computer) { final Intent intent = new Intent(SdkSandboxManagerLocal.SERVICE_INTERFACE); - final List<ResolveInfo> matches = queryIntentServicesInternal( + final List<ResolveInfo> matches = computer.queryIntentServicesInternal( intent, /* resolvedType= */ null, MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, @@ -3701,22 +3470,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Nullable - private String getDeviceConfiguratorPackageName() { - return ensureSystemPackageName(mContext.getString( - R.string.config_deviceConfiguratorPackageName)); - } - - public @Nullable String getAmbientContextDetectionPackageName() { - return ensureSystemPackageName(getPackageFromComponentString( - R.string.config_defaultAmbientContextDetectionService)); - } - - public String getOverlayConfigSignaturePackageName() { - return ensureSystemPackageName(mInjector.getSystemConfig() - .getOverlayConfigSignaturePackage()); - } - - @Nullable private String getRetailDemoPackageName() { final String predefinedPkgName = mContext.getString(R.string.config_retailDemoPackage); final String predefinedSignature = mContext.getString( @@ -3752,14 +3505,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Nullable - private String getRecentsPackageName() { - return ensureSystemPackageName( - getPackageFromComponentString(R.string.config_recentsComponentName)); - - } - - @Nullable - private String getPackageFromComponentString(@StringRes int stringResId) { + String getPackageFromComponentString(@StringRes int stringResId) { final String componentString = mContext.getString(stringResId); if (TextUtils.isEmpty(componentString)) { return null; @@ -3772,16 +3518,17 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Nullable - private String ensureSystemPackageName(@Nullable String packageName) { + String ensureSystemPackageName(@NonNull Computer snapshot, + @Nullable String packageName) { if (packageName == null) { return null; } final long token = Binder.clearCallingIdentity(); try { - if (mIPackageManager.getPackageInfo(packageName, MATCH_FACTORY_ONLY, + if (snapshot.getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) { PackageInfo packageInfo = - mIPackageManager.getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM); + snapshot.getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM); if (packageInfo != null) { EventLog.writeEvent(0x534e4554, "145981139", packageInfo.applicationInfo.uid, ""); @@ -3863,8 +3610,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService private void setEnabledSettings(List<ComponentEnabledSetting> settings, int userId, String callingPackage) { final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, - true /* checkShell */, "set enabled"); + // TODO: This method is not properly snapshotified beyond this call + final Computer preLockSnapshot = snapshotComputer(); + preLockSnapshot.enforceCrossUserPermission(callingUid, userId, + false /* requireFullPermission */, true /* checkShell */, "set enabled"); final int targetSize = settings.size(); for (int i = 0; i < targetSize; i++) { @@ -3920,6 +3669,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService final Map<String, PackageSetting> pkgSettings = new ArrayMap<>(targetSize); // reader synchronized (mLock) { + final Computer snapshot = snapshotComputer(); // Checks for target packages for (int i = 0; i < targetSize; i++) { final ComponentEnabledSetting setting = settings.get(i); @@ -3929,13 +3679,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService continue; } final boolean isCallerTargetApp = ArrayUtils.contains( - mIPackageManager.getPackagesForUid(callingUid), packageName); + snapshot.getPackagesForUid(callingUid), packageName); final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName); // Limit who can change which apps if (!isCallerTargetApp) { // Don't allow apps that don't have permission to modify other apps if (!allowedByPermission - || shouldFilterApplication(pkgSetting, callingUid, userId)) { + || snapshot.shouldFilterApplication(pkgSetting, callingUid, userId)) { throw new SecurityException("Attempt to change component state; " + "pid=" + Binder.getCallingPid() + ", uid=" + callingUid @@ -4108,12 +3858,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService final long callingId = Binder.clearCallingIdentity(); try { + final Computer newSnapshot = snapshotComputer(); for (int i = 0; i < sendNowBroadcasts.size(); i++) { final String packageName = sendNowBroadcasts.keyAt(i); final ArrayList<String> components = sendNowBroadcasts.valueAt(i); final int packageUid = UserHandle.getUid( userId, pkgSettings.get(packageName).getAppId()); - sendPackageChangedBroadcast(packageName, false /* dontKillApp */, + sendPackageChangedBroadcast(newSnapshot, packageName, false /* dontKillApp */, components, packageUid, null /* reason */); } } finally { @@ -4137,13 +3888,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService pkgSetting.setEnabled(newState, userId, callingPackage); if ((newState == COMPONENT_ENABLED_STATE_DISABLED_USER || newState == COMPONENT_ENABLED_STATE_DISABLED) - && mIPackageManager.checkPermission(Manifest.permission.SUSPEND_APPS, - packageName, userId) == PERMISSION_GRANTED) { + && checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId) + == PERMISSION_GRANTED) { // This app should not generally be allowed to get disabled by the UI, but // if it ever does, we don't want to end up with some of the user's apps // permanently suspended. unsuspendForSuspendingPackage(computer, packageName, userId); - removeAllDistractingPackageRestrictions(userId); + removeAllDistractingPackageRestrictions(computer, userId); } success = true; } else { @@ -4194,25 +3945,20 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - void sendPackageChangedBroadcast(String packageName, + void sendPackageChangedBroadcast(@NonNull Computer snapshot, String packageName, boolean dontKillApp, ArrayList<String> componentNames, int packageUid, String reason) { final int userId = UserHandle.getUserId(packageUid); - final boolean isInstantApp = isInstantAppInternal(packageName, userId, Process.SYSTEM_UID); + 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 = getBroadcastAllowList( + final SparseArray<int[]> broadcastAllowList = snapshot.getBroadcastAllowList( packageName, userIds, isInstantApp); mHandler.post(() -> mBroadcastHelper.sendPackageChangedBroadcast( packageName, dontKillApp, componentNames, packageUid, reason, userIds, instantUserIds, broadcastAllowList)); } - @Nullable - private SparseArray<int[]> getBroadcastAllowList(@NonNull String packageName, - @UserIdInt int[] userIds, boolean isInstantApp) { - return mComputer.getBroadcastAllowList(packageName, userIds, isInstantApp); - } - /** * Used by SystemServer */ @@ -4296,7 +4042,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService // Now that we're mostly running, clean up stale users and apps mUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL); - storageEventHelper.reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL); + storageEventHelper.reconcileApps(snapshotComputer(), StorageManager.UUID_PRIVATE_INTERNAL); mPermissionManager.onSystemReady(); @@ -4308,7 +4054,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService final int livingUserCount = livingUsers.size(); for (int i = 0; i < livingUserCount; i++) { final int userId = livingUsers.get(i).id; - if (mPmInternal.isPermissionUpgradeNeeded(userId)) { + if (mSettings.isPermissionUpgradeNeeded(userId)) { grantPermissionsUserIds = ArrayUtils.appendInt( grantPermissionsUserIds, userId); } @@ -4350,11 +4096,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService if (packageName == null) { return; } - AndroidPackage pkg = mPackages.get(packageName); + final Computer snapshot = snapshotComputer(); + AndroidPackage pkg = snapshot.getPackage(packageName); if (pkg == null) { return; } - sendPackageChangedBroadcast(pkg.getPackageName(), + sendPackageChangedBroadcast(snapshot, pkg.getPackageName(), true /* dontKillApp */, new ArrayList<>(Collections.singletonList(pkg.getPackageName())), pkg.getUid(), @@ -4407,14 +4154,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mSnapshotStatistics.dump(pw, " ", now, hits, -1, isBrief); } - /** - * Dump package manager states to the file according to a given dumping type of - * {@link DumpState}. - */ - void dumpComputer(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState) { - mComputer.dump(type, fd, pw, dumpState); - } - //TODO: b/111402650 private void disableSkuSpecificApps() { String[] apkList = mContext.getResources().getStringArray( @@ -4428,10 +4167,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService if (!TextUtils.isEmpty(sku) && ArrayUtils.contains(skuArray, sku)) { return; } + final Computer snapshot = snapshotComputer(); for (String packageName : apkList) { - mIPackageManager.setSystemAppHiddenUntilInstalled(packageName, true); + setSystemAppHiddenUntilInstalled(snapshot, packageName, true); for (UserInfo user : mInjector.getUserManagerInternal().getUsers(false)) { - mIPackageManager.setSystemAppInstallState(packageName, false, user.id); + setSystemAppInstallState(snapshot, packageName, false, user.id); } } } @@ -4524,7 +4264,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mPermissionManager.writeLegacyPermissionStateTEMP(); mSettings.readPermissionStateForUserSyncLPr(userId); mPermissionManager.readLegacyPermissionStateTEMP(); - return mPmInternal.isPermissionUpgradeNeeded(userId); + return mSettings.isPermissionUpgradeNeeded(userId); } } @@ -4544,12 +4284,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - boolean userNeedsBadging(int userId) { - return mUserNeedsBadging.get(userId); - } - - private void deletePackageIfUnused(final String packageName) { - PackageStateInternal ps = getPackageStateInternal(packageName); + private void deletePackageIfUnused(@NonNull Computer snapshot, final String packageName) { + PackageStateInternal ps = snapshot.getPackageStateInternal(packageName); if (ps == null) { return; } @@ -4567,41 +4303,101 @@ public class PackageManagerService implements PackageSender, TestUtilityService 0, PackageManager.DELETE_ALL_USERS, true /*removedBySystem*/)); } - private AndroidPackage getPackage(String packageName) { - return mComputer.getPackage(packageName); + void deletePreloadsFileCache() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CLEAR_APP_CACHE, + "deletePreloadsFileCache"); + File dir = Environment.getDataPreloadsFileCacheDirectory(); + Slog.i(PackageManagerService.TAG, "Deleting preloaded file cache " + dir); + FileUtils.deleteContents(dir); } - private AndroidPackage getPackage(int uid) { - return mComputer.getPackage(uid); - } + void setSystemAppHiddenUntilInstalled(@NonNull Computer snapshot, String packageName, + boolean hidden) { + final int callingUid = Binder.getCallingUid(); + final boolean calledFromSystemOrPhone = callingUid == Process.PHONE_UID + || callingUid == Process.SYSTEM_UID; + if (!calledFromSystemOrPhone) { + mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, + "setSystemAppHiddenUntilInstalled"); + } - private SigningDetails getSigningDetails(@NonNull String packageName) { - return mComputer.getSigningDetails(packageName); - } + final PackageStateInternal stateRead = snapshot.getPackageStateInternal(packageName); + if (stateRead == null || !stateRead.isSystem() || stateRead.getPkg() == null) { + return; + } + if (stateRead.getPkg().isCoreApp() && !calledFromSystemOrPhone) { + throw new SecurityException("Only system or phone callers can modify core apps"); + } - private SigningDetails getSigningDetails(int uid) { - return mComputer.getSigningDetails(uid); + commitPackageStateMutation(null, mutator -> { + mutator.forPackage(packageName) + .setHiddenUntilInstalled(hidden); + mutator.forDisabledSystemPackage(packageName) + .setHiddenUntilInstalled(hidden); + }); } - private boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) { - return mComputer.filterAppAccess(pkg, callingUid, userId); - } + boolean setSystemAppInstallState(@NonNull Computer snapshot, String packageName, + boolean installed, int userId) { + final int callingUid = Binder.getCallingUid(); + final boolean calledFromSystemOrPhone = callingUid == Process.PHONE_UID + || callingUid == Process.SYSTEM_UID; + if (!calledFromSystemOrPhone) { + mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, + "setSystemAppHiddenUntilInstalled"); + } - private boolean filterAppAccess(String packageName, int callingUid, int userId) { - return mComputer.filterAppAccess(packageName, callingUid, userId); - } + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); + // The target app should always be in system + if (packageState == null || !packageState.isSystem() || packageState.getPkg() == null) { + return false; + } + if (packageState.getPkg().isCoreApp() && !calledFromSystemOrPhone) { + throw new SecurityException("Only system or phone callers can modify core apps"); + } + // Check if the install state is the same + if (packageState.getUserStateOrDefault(userId).isInstalled() == installed) { + return false; + } - private boolean filterAppAccess(int uid, int callingUid) { - return mComputer.filterAppAccess(uid, callingUid); - } + final long callingId = Binder.clearCallingIdentity(); + try { + if (installed) { + // install the app from uninstalled state + mInstallPackageHelper.installExistingPackageAsUser( + packageName, + userId, + PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, + PackageManager.INSTALL_REASON_DEVICE_SETUP, + null, + null); + return true; + } - @Nullable - private int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId) { - return mComputer.getVisibilityAllowList(packageName, userId); + // uninstall the app from installed state + deletePackageVersioned( + new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), + new PackageManager.LegacyPackageDeleteObserver(null).getBinder(), + userId, + PackageManager.DELETE_SYSTEM_APP); + return true; + } finally { + Binder.restoreCallingIdentity(callingId); + } } - boolean canQueryPackage(int callingUid, @Nullable String targetPackageName) { - return mComputer.canQueryPackage(callingUid, targetPackageName); + void finishPackageInstall(int token, boolean didLaunch) { + PackageManagerServiceUtils.enforceSystemOrRoot( + "Only the system is allowed to finish installs"); + + if (PackageManagerService.DEBUG_INSTALL) { + Slog.v(PackageManagerService.TAG, "BM finishing package install for " + token); + } + Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "restore", token); + + final Message msg = mHandler.obtainMessage(PackageManagerService.POST_INSTALL, token, + didLaunch ? 1 : 0); + mHandler.sendMessage(msg); } void checkPackageStartable(@NonNull Computer snapshot, @NonNull String packageName, @@ -4689,71 +4485,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - public class IPackageManagerImpl extends IPackageManager.Stub { + public class IPackageManagerImpl extends IPackageManagerBase { - @Override - public boolean activitySupportsIntent(ComponentName component, Intent intent, - String resolvedType) { - return mComputer.activitySupportsIntent(mResolveComponentName, component, intent, - resolvedType); - } - - @Override - public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage, - int sourceUserId, int targetUserId, int flags) { - PackageManagerService.this.addCrossProfileIntentFilter( - new WatchedIntentFilter(intentFilter), ownerPackage, sourceUserId, targetUserId, - flags); - } - - // NOTE: Can't remove due to unsupported app usage - @Override - public boolean addPermission(PermissionInfo info) { - // Because this is accessed via the package manager service AIDL, - // go through the permission manager service AIDL - return mContext.getSystemService(PermissionManager.class).addPermission(info, false); - } - - // NOTE: Can't remove due to unsupported app usage - @Override - public boolean addPermissionAsync(PermissionInfo info) { - // Because this is accessed via the package manager service AIDL, - // go through the permission manager service AIDL - return mContext.getSystemService(PermissionManager.class).addPermission(info, true); - } - - @Override - public void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity, - int userId) { - mPreferredActivityHelper.addPersistentPreferredActivity(new WatchedIntentFilter(filter), - activity, userId); - } - - @Override - public void addPreferredActivity(IntentFilter filter, int match, - ComponentName[] set, ComponentName activity, int userId, boolean removeExisting) { - mPreferredActivityHelper.addPreferredActivity(new WatchedIntentFilter(filter), match, - set, activity, true, userId, "Adding preferred", removeExisting); - } - - /* - * Returns if intent can be forwarded from the sourceUserId to the targetUserId - */ - @Override - public boolean canForwardTo(@NonNull Intent intent, @Nullable String resolvedType, - @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { - return mComputer.canForwardTo(intent, resolvedType, sourceUserId, targetUserId); - } - - @Override - public boolean canRequestPackageInstalls(String packageName, int userId) { - return mComputer.canRequestPackageInstalls(packageName, Binder.getCallingUid(), userId, - true /* throwIfPermNotDeclared*/); - } - - @Override - public String[] canonicalToCurrentPackageNames(String[] names) { - return mComputer.canonicalToCurrentPackageNames(names); + public IPackageManagerImpl() { + super(PackageManagerService.this, mContext, mDexOptHelper, mModuleInfoProvider, + mPreferredActivityHelper, mResolveIntentHelper, mDomainVerificationManager, + mDomainVerificationConnection, mInstallerService, mPackageProperty, + mResolveComponentName, mInstantAppResolverSettingsComponent, + mRequiredSdkSandboxPackage, mServicesExtensionPackageName, + mSharedSystemSharedLibraryPackageName); } @Override @@ -4762,33 +4502,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService .checkPackageStartable(snapshotComputer(), packageName, userId); } - // NOTE: Can't remove due to unsupported app usage - @Override - public int checkPermission(String permName, String pkgName, int userId) { - return PackageManagerService.this.checkPermission(permName, pkgName, userId); - } - - @Override - public int checkSignatures(@NonNull String pkg1, @NonNull String pkg2) { - return mComputer.checkSignatures(pkg1, pkg2); - } - - @Override - public int checkUidPermission(String permName, int uid) { - return mComputer.checkUidPermission(permName, uid); - } - - @Override - public int checkUidSignatures(int uid1, int uid2) { - return mComputer.checkUidSignatures(uid1, uid2); - } - @Override public void clearApplicationProfileData(String packageName) { PackageManagerServiceUtils.enforceSystemOrRoot( "Only the system can clear all profile data"); - final AndroidPackage pkg = getPackage(packageName); + final Computer snapshot = snapshotComputer(); + final AndroidPackage pkg = snapshot.getPackage(packageName); try (PackageFreezer ignored = freezePackage(packageName, "clearApplicationProfileData")) { synchronized (mInstallLock) { mAppDataHelper.clearAppProfilesLIF(pkg); @@ -4803,10 +4523,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService android.Manifest.permission.CLEAR_APP_USER_DATA, null); final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "clear application data"); - if (mComputer.getPackageStateFiltered(packageName, callingUid, userId) == null) { + if (snapshot.getPackageStateFiltered(packageName, callingUid, userId) == null) { if (observer != null) { mHandler.post(() -> { try { @@ -4831,7 +4552,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService try (PackageFreezer freezer = freezePackage(packageName, "clearApplicationUserData")) { synchronized (mInstallLock) { - succeeded = clearApplicationUserDataLIF(packageName, userId); + succeeded = clearApplicationUserDataLIF(snapshotComputer(), packageName, + userId); } mInstantAppRegistry.deleteInstantApplicationMetadata(packageName, userId); synchronized (mLock) { @@ -4849,8 +4571,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService } if (checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId) == PERMISSION_GRANTED) { - unsuspendForSuspendingPackage(snapshotComputer(), packageName, userId); - removeAllDistractingPackageRestrictions(userId); + final Computer snapshot = snapshotComputer(); + unsuspendForSuspendingPackage(snapshot, packageName, userId); + removeAllDistractingPackageRestrictions(snapshot, userId); flushPackageRestrictionsAsUserInternalLocked(userId); } } @@ -4870,7 +4593,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); final int callingUid = Binder.getCallingUid(); - enforceOwnerRights(ownerPackage, callingUid); + final Computer snapshot = snapshotComputer(); + enforceOwnerRights(snapshot, ownerPackage, callingUid); PackageManagerServiceUtils.enforceShellRestriction(mInjector.getUserManagerInternal(), UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId); synchronized (mLock) { @@ -4888,22 +4612,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void clearPackagePersistentPreferredActivities(String packageName, int userId) { - mPreferredActivityHelper.clearPackagePersistentPreferredActivities(packageName, userId); - } - - @Override - public void clearPackagePreferredActivities(String packageName) { - mPreferredActivityHelper.clearPackagePreferredActivities(packageName); - } - - @Override - public String[] currentToCanonicalPackageNames(String[] names) { - return mComputer.currentToCanonicalPackageNames(names); - } - - @Override - public void deleteApplicationCacheFiles(final String packageName, + public final void deleteApplicationCacheFiles(final String packageName, final IPackageDataObserver observer) { final int userId = UserHandle.getCallingUserId(); deleteApplicationCacheFilesAsUser(packageName, userId, observer); @@ -4928,17 +4637,18 @@ public class PackageManagerService implements PackageSender, TestUtilityService mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERNAL_DELETE_CACHE_FILES, null); } - enforceCrossUserPermission(callingUid, userId, /* requireFullPermission= */ true, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, /* requireFullPermission= */ true, /* checkShell= */ false, "delete application cache files"); final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_INSTANT_APPS); - final AndroidPackage pkg = getPackage(packageName); - // Queue up an async operation since the package deletion may take a little while. mHandler.post(() -> { - final PackageStateInternal ps = - pkg == null ? null : getPackageStateInternal(pkg.getPackageName()); + // Snapshot in the Handler Runnable since this may be deferred quite a bit + // TODO: Is this and the later mInstallLock re-snapshot necessary? + final Computer newSnapshot = snapshotComputer(); + final PackageStateInternal ps = newSnapshot.getPackageStateInternal(packageName); boolean doClearData = true; if (ps != null) { final boolean targetIsInstantApp = @@ -4949,6 +4659,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService if (doClearData) { synchronized (mInstallLock) { final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL; + // Snapshot again after mInstallLock? + final AndroidPackage pkg = snapshotComputer().getPackage(packageName); // We're only clearing cache files, so we don't care if the // app is unfrozen and still able to run mAppDataHelper.clearAppDataLIF(pkg, userId, @@ -4968,47 +4680,18 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void deleteExistingPackageAsUser(VersionedPackage versionedPackage, - final IPackageDeleteObserver2 observer, final int userId) { - PackageManagerService.this.deleteExistingPackageAsUser(versionedPackage, observer, - userId); - } - - @Override - public void deletePackageAsUser(String packageName, int versionCode, - IPackageDeleteObserver observer, int userId, int flags) { - deletePackageVersioned(new VersionedPackage(packageName, versionCode), - new PackageManager.LegacyPackageDeleteObserver(observer).getBinder(), userId, flags); - } - - @Override - public void deletePackageVersioned(VersionedPackage versionedPackage, - final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) { - PackageManagerService.this.deletePackageVersioned(versionedPackage, observer, - userId, deleteFlags); - } - - @Override - public void deletePreloadsFileCache() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CLEAR_APP_CACHE, - "deletePreloadsFileCache"); - File dir = Environment.getDataPreloadsFileCacheDirectory(); - Slog.i(PackageManagerService.TAG, "Deleting preloaded file cache " + dir); - FileUtils.deleteContents(dir); - } - - @Override public void dumpProfiles(String packageName) { /* Only the shell, root, or the app user should be able to dump profiles. */ final int callingUid = Binder.getCallingUid(); - final String[] callerPackageNames = getPackagesForUid(callingUid); + final Computer snapshot = snapshotComputer(); + final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid); if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID && !ArrayUtils.contains(callerPackageNames, packageName)) { throw new SecurityException("dumpProfiles"); } - AndroidPackage pkg = mComputer.getPackage(packageName); + AndroidPackage pkg = snapshot.getPackage(packageName); if (pkg == null) { throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -5062,46 +4745,25 @@ public class PackageManagerService implements PackageSender, TestUtilityService }); } - @Override - public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) { - return mPreferredActivityHelper.findPersistentPreferredActivity(intent, userId); - } - - @Override - public void finishPackageInstall(int token, boolean didLaunch) { - PackageManagerServiceUtils.enforceSystemOrRoot( - "Only the system is allowed to finish installs"); - - if (PackageManagerService.DEBUG_INSTALL) { - Slog.v(PackageManagerService.TAG, "BM finishing package install for " + token); - } - Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "restore", token); - - final Message msg = mHandler.obtainMessage(PackageManagerService.POST_INSTALL, token, didLaunch ? 1 : 0); - mHandler.sendMessage(msg); - } - @WorkerThread @Override public void flushPackageRestrictionsAsUser(int userId) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { + final Computer snapshot = snapshotComputer(); + final int callingUid = Binder.getCallingUid(); + if (snapshot.getInstantAppPackageName(callingUid) != null) { return; } if (!mUserManager.exists(userId)) { return; } - enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission*/, - false /* checkShell */, "flushPackageRestrictions"); + snapshot.enforceCrossUserPermission(callingUid, userId, + false /* requireFullPermission*/, false /* checkShell */, + "flushPackageRestrictions"); synchronized (mLock) { flushPackageRestrictionsAsUserInternalLocked(userId); } } - @Override - public void forceDexOpt(String packageName) { - mDexOptHelper.forceDexOpt(packageName); - } - @Override public void freeStorage(final String volumeUuid, final long freeStorageSize, @@ -5150,83 +4812,17 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public ActivityInfo getActivityInfo(ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, int userId) { - return mComputer.getActivityInfo(component, flags, userId); - } - - @NonNull - @Override - public ParceledListSlice<IntentFilter> getAllIntentFilters(@NonNull String packageName) { - return mComputer.getAllIntentFilters(packageName); - } - - @Override - public List<String> getAllPackages() { - return mComputer.getAllPackages(); - } - - // NOTE: Can't remove due to unsupported app usage - @NonNull - @Override - public String[] getAppOpPermissionPackages(@NonNull String permissionName) { - return mComputer.getAppOpPermissionPackages(permissionName); - } - - @Override - public String getAppPredictionServicePackageName() { - return ensureSystemPackageName( - getPackageFromComponentString(R.string.config_defaultAppPredictionService)); - } - - @PackageManager.EnabledState - @Override - public int getApplicationEnabledSetting(@NonNull String packageName, @UserIdInt int userId) { - return mComputer.getApplicationEnabledSetting(packageName, userId); - } - - /** - * Returns true if application is not found or there was an error. Otherwise it returns - * the hidden state of the package for the given user. - */ - @Override - public boolean getApplicationHiddenSettingAsUser(@NonNull String packageName, - @UserIdInt int userId) { - return mComputer.getApplicationHiddenSettingAsUser(packageName, userId); - } - - @Override - public ApplicationInfo getApplicationInfo(String packageName, - @PackageManager.ApplicationInfoFlagsBits long flags, int userId) { - return mComputer.getApplicationInfo(packageName, flags, userId); - } - - @Override - public IArtManager getArtManager() { - return mArtManagerService; - } - - @Override - public @Nullable String getAttentionServicePackageName() { - return ensureSystemPackageName( - getPackageFromComponentString(R.string.config_defaultAttentionService)); - } - - @Override - public boolean getBlockUninstallForUser(@NonNull String packageName, @UserIdInt int userId) { - return mComputer.getBlockUninstallForUser(packageName, userId); - } - - @Override public ChangedPackages getChangedPackages(int sequenceNumber, int userId) { final int callingUid = Binder.getCallingUid(); - if (getInstantAppPackageName(callingUid) != null) { + final Computer snapshot = snapshotComputer(); + if (snapshot.getInstantAppPackageName(callingUid) != null) { return null; } if (!mUserManager.exists(userId)) { return null; } - enforceCrossUserPermission(callingUid, userId, false, false, "getChangedPackages"); + snapshot.enforceCrossUserPermission(callingUid, userId, false, false, + "getChangedPackages"); final ChangedPackages changedPackages = mChangedPackagesTracker.getChangedPackages( sequenceNumber, userId); @@ -5234,8 +4830,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService final List<String> packageNames = changedPackages.getPackageNames(); for (int index = packageNames.size() - 1; index >= 0; index--) { // Filter out the changes if the calling package should not be able to see it. - final PackageSetting ps = mSettings.getPackageLPr(packageNames.get(index)); - if (shouldFilterApplication(ps, callingUid, userId)) { + final PackageStateInternal packageState = + snapshot.getPackageStateInternal(packageNames.get(index)); + if (snapshot.shouldFilterApplication(packageState, callingUid, userId)) { packageNames.remove(index); } } @@ -5245,41 +4842,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public int getComponentEnabledSetting(@NonNull ComponentName component, int userId) { - return mComputer.getComponentEnabledSetting(component, Binder.getCallingUid(), userId); - } - - @Override - public String getContentCaptureServicePackageName() { - return ensureSystemPackageName( - getPackageFromComponentString(R.string.config_defaultContentCaptureService)); - } - - @Nullable - @Override - public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries( - @NonNull String packageName, @PackageManager.PackageInfoFlagsBits long flags, - @NonNull int userId) { - return mComputer.getDeclaredSharedLibraries(packageName, flags, userId); - } - - /** - * Non-Binder method, support for the backup/restore mechanism: write the - * default browser (etc) settings in its canonical XML format. Returns the default - * browser XML representation as a byte array, or null if there is none. - */ - @Override - public byte[] getDefaultAppsBackup(int userId) { - return mPreferredActivityHelper.getDefaultAppsBackup(userId); - } - - @Override - public String getDefaultTextClassifierPackageName() { - return ensureSystemPackageName( - mContext.getString(R.string.config_servicesExtensionPackage)); - } - - @Override public byte[] getDomainVerificationBackup(int userId) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Only the system may call getDomainVerificationBackup()"); @@ -5301,17 +4863,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public int getFlagsForUid(int uid) { - return mComputer.getFlagsForUid(uid); - } - - @Nullable - @Override - public CharSequence getHarmfulAppWarning(@NonNull String packageName, @UserIdInt int userId) { - return mComputer.getHarmfulAppWarning(packageName, userId); - } - - @Override public IBinder getHoldLockToken() { if (!Build.IS_DEBUGGABLE) { throw new SecurityException("getHoldLockToken requires a debuggable build"); @@ -5327,72 +4878,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return null; - } - return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId()); - } - - public String getIncidentReportApproverPackageName() { - return ensureSystemPackageName(mContext.getString( - R.string.config_incidentReportApproverPackage)); - } - - @Override - public int getInstallLocation() { - // allow instant app access - return android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, - InstallLocationUtils.APP_INSTALL_AUTO); - } - - @PackageManager.InstallReason - @Override - public int getInstallReason(@NonNull String packageName, @UserIdInt int userId) { - return mComputer.getInstallReason(packageName, userId); - } - - @Override - @Nullable - public InstallSourceInfo getInstallSourceInfo(@NonNull String packageName) { - return mComputer.getInstallSourceInfo(packageName); - } - - @Override - public ParceledListSlice<ApplicationInfo> getInstalledApplications( - @PackageManager.ApplicationInfoFlagsBits long flags, int userId) { - final int callingUid = Binder.getCallingUid(); - return new ParceledListSlice<>( - mComputer.getInstalledApplications(flags, userId, callingUid)); - } - - @Override - public List<ModuleInfo> getInstalledModules(int flags) { - return mModuleInfoProvider.getInstalledModules(flags); - } - - @Override - public ParceledListSlice<PackageInfo> getInstalledPackages( - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - return mComputer.getInstalledPackages(flags, userId); - } - - @Nullable - @Override - public String getInstallerPackageName(@NonNull String packageName) { - return mComputer.getInstallerPackageName(packageName); - } - - @Override public String getInstantAppAndroidId(String packageName, int userId) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_INSTANT_APPS, - "getInstantAppAndroidId"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_INSTANT_APPS, "getInstantAppAndroidId"); + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, false /* checkShell */, "getInstantAppAndroidId"); // Make sure the target is an Instant App. - if (!isInstantApp(packageName, userId)) { + if (!snapshot.isInstantApp(packageName, userId)) { return null; } return mInstantAppRegistry.getInstantAppAndroidId(packageName, userId); @@ -5404,13 +4898,14 @@ public class PackageManagerService implements PackageSender, TestUtilityService return null; } - enforceCrossUserPermission(Binder.getCallingUid(), userId, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, false /* checkShell */, "getInstantAppCookie"); - if (!isCallerSameApp(packageName, Binder.getCallingUid())) { + if (!snapshot.isCallerSameApp(packageName, Binder.getCallingUid())) { return null; } - PackageStateInternal packageState = getPackageStateInternal(packageName); + PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState == null || packageState.getPkg() == null) { return null; } @@ -5423,11 +4918,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService return null; } - if (!canViewInstantApps(Binder.getCallingUid(), userId)) { + final Computer snapshot = snapshotComputer(); + if (!snapshot.canViewInstantApps(Binder.getCallingUid(), userId)) { mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_INSTANT_APPS, "getInstantAppIcon"); } - enforceCrossUserPermission(Binder.getCallingUid(), userId, + snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, false /* checkShell */, "getInstantAppIcon"); @@ -5435,76 +4931,31 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public ComponentName getInstantAppInstallerComponent() { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return null; - } - return mInstantAppInstallerActivity == null - ? null : mInstantAppInstallerActivity.getComponentName(); - } - - @Override - public @Nullable ComponentName getInstantAppResolverComponent() { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return null; - } - return getInstantAppResolver(); - } - - @Override - public ComponentName getInstantAppResolverSettingsComponent() { - return mInstantAppResolverSettingsComponent; - } - - @Override public ParceledListSlice<InstantAppInfo> getInstantApps(int userId) { - if (PackageManagerService.HIDE_EPHEMERAL_APIS) { + if (HIDE_EPHEMERAL_APIS) { return null; } - if (!canViewInstantApps(Binder.getCallingUid(), userId)) { + + final Computer snapshot = snapshotComputer(); + if (!snapshot.canViewInstantApps(Binder.getCallingUid(), userId)) { mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_INSTANT_APPS, "getEphemeralApplications"); } - enforceCrossUserPermission(Binder.getCallingUid(), userId, + snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, false /* checkShell */, "getEphemeralApplications"); - Computer computer = snapshotComputer(); - List<InstantAppInfo> instantApps = mInstantAppRegistry.getInstantApps(computer, userId); + List<InstantAppInfo> instantApps = mInstantAppRegistry.getInstantApps(snapshot, userId); if (instantApps != null) { return new ParceledListSlice<>(instantApps); } return null; } - @Nullable - @Override - public InstrumentationInfo getInstrumentationInfo(@NonNull ComponentName component, int flags) { - return mComputer.getInstrumentationInfo(component, flags); - } - - @Deprecated - @Override - public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications( - String packageName) { - return ParceledListSlice.emptyList(); - } - - @Deprecated - @Override - public int getIntentVerificationStatus(String packageName, int userId) { - return mDomainVerificationManager.getLegacyState(packageName, userId); - } - - @Nullable - @Override - public KeySet getKeySetByAlias(@NonNull String packageName, @NonNull String alias) { - return mComputer.getKeySetByAlias(packageName, alias); - } - @Override public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) { - return mPreferredActivityHelper.getLastChosenActivity(intent, resolvedType, flags); + return mPreferredActivityHelper.getLastChosenActivity(snapshotComputer(), intent, + resolvedType, flags); } @Override @@ -5516,13 +4967,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public List<String> getMimeGroup(String packageName, String mimeGroup) { - enforceOwnerRights(packageName, Binder.getCallingUid()); - return getMimeGroupInternal(packageName, mimeGroup); - } - - @Override - public ModuleInfo getModuleInfo(String packageName, @PackageManager.ModuleInfoFlags int flags) { - return PackageManagerService.this.getModuleInfo(packageName, flags); + final Computer snapshot = snapshotComputer(); + enforceOwnerRights(snapshot, packageName, Binder.getCallingUid()); + return getMimeGroupInternal(snapshot, packageName, mimeGroup); } @Override @@ -5532,99 +4979,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mMoveCallbacks.mLastStatus.get(moveId); } - @Nullable - @Override - public String getNameForUid(int uid) { - return mComputer.getNameForUid(uid); - } - - @Nullable - @Override - public String[] getNamesForUids(@NonNull int[] uids) { - return mComputer.getNamesForUids(uids); - } - - @Override - public int[] getPackageGids(String packageName, @PackageManager.PackageInfoFlagsBits long flags, - int userId) { - return mComputer.getPackageGids(packageName, flags, userId); - } - - @Override - public PackageInfo getPackageInfo(String packageName, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - return mComputer.getPackageInfo(packageName, flags, userId); - } - - @Override - public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - return mComputer.getPackageInfoInternal(versionedPackage.getPackageName(), - versionedPackage.getLongVersionCode(), flags, Binder.getCallingUid(), userId); - } - - @Override - public IPackageInstaller getPackageInstaller() { - // Return installer service for internal calls. - if (PackageManagerServiceUtils.isSystemOrRoot()) { - return mInstallerService; - } - // Return null for InstantApps. - if (snapshotComputer().getInstantAppPackageName(Binder.getCallingUid()) != null) { - return null; - } - return mInstallerService; - } - - @Override - public void getPackageSizeInfo(final String packageName, int userId, - final IPackageStatsObserver observer) { - throw new UnsupportedOperationException( - "Shame on you for calling the hidden API getPackageSizeInfo(). Shame!"); - } - - @Override - public int getPackageUid(@NonNull String packageName, - @PackageManager.PackageInfoFlagsBits long flags, @UserIdInt int userId) { - return mComputer.getPackageUid(packageName, flags, userId); - } - - /** - * <em>IMPORTANT:</em> Not all packages returned by this method may be known - * to the system. There are two conditions in which this may occur: - * <ol> - * <li>The package is on adoptable storage and the device has been removed</li> - * <li>The package is being removed and the internal structures are partially updated</li> - * </ol> - * The second is an artifact of the current data structures and should be fixed. See - * b/111075456 for one such instance. - * This binder API is cached. If the algorithm in this method changes, - * or if the underlying objecs (as returned by getSettingLPr()) change - * then the logic that invalidates the cache must be revisited. See - * calls to invalidateGetPackagesForUidCache() to locate the points at - * which the cache is invalidated. - */ - @Override - public String[] getPackagesForUid(int uid) { - final int callingUid = Binder.getCallingUid(); - final int userId = UserHandle.getUserId(uid); - mComputer.enforceCrossUserOrProfilePermission(callingUid, userId, - /* requireFullPermission */ false, - /* checkShell */ false, "getPackagesForUid"); - return mComputer.getPackagesForUid(uid); - } - - @Override - public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions( - @NonNull String[] permissions, @PackageManager.PackageInfoFlagsBits long flags, - @UserIdInt int userId) { - return mComputer.getPackagesHoldingPermissions(permissions, flags, userId); - } - @Override public String getPermissionControllerPackageName() { final int callingUid = Binder.getCallingUid(); - if (mComputer.getPackageStateFiltered(mRequiredPermissionControllerPackage, + final Computer snapshot = snapshotComputer(); + if (snapshot.getPackageStateFiltered(mRequiredPermissionControllerPackage, callingUid, UserHandle.getUserId(callingUid)) != null) { return mRequiredPermissionControllerPackage; } @@ -5632,73 +4991,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService throw new IllegalStateException("PermissionController is not found"); } - // NOTE: Can't remove due to unsupported app usage - @Override - public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) { - return PackageManagerService.this.getPermissionGroupInfo(groupName, flags); - } - - @Override - public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return ParceledListSlice.emptyList(); - } - return new ParceledListSlice<>(mComputer.getPersistentApplications(mSafeMode, flags)); - } - - @Override - public int getPreferredActivities(List<IntentFilter> outFilters, - List<ComponentName> outActivities, String packageName) { - return mPreferredActivityHelper.getPreferredActivities(outFilters, outActivities, - packageName, snapshotComputer()); - } - - /** - * Non-Binder method, support for the backup/restore mechanism: write the - * full set of preferred activities in its canonical XML format. Returns the - * XML output as a byte array, or null if there is none. - */ - @Override - public byte[] getPreferredActivityBackup(int userId) { - return mPreferredActivityHelper.getPreferredActivityBackup(userId); - } - - @Override - public int getPrivateFlagsForUid(int uid) { - return mComputer.getPrivateFlagsForUid(uid); - } - - @Override - public PackageManager.Property getProperty(String propertyName, String packageName, String className) { - Objects.requireNonNull(propertyName); - Objects.requireNonNull(packageName); - PackageStateInternal packageState = mComputer.getPackageStateFiltered(packageName, - Binder.getCallingUid(), UserHandle.getCallingUserId()); - if (packageState == null) { - return null; - } - return mPackageProperty.getProperty(propertyName, packageName, className); - } - - @Nullable - @Override - public ProviderInfo getProviderInfo(@NonNull ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { - return mComputer.getProviderInfo(component, flags, userId); - } - - @Override - public ActivityInfo getReceiverInfo(ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, int userId) { - return mComputer.getReceiverInfo(component, flags, userId); - } - - @Override - public @Nullable String getRotationResolverPackageName() { - return ensureSystemPackageName( - getPackageFromComponentString(R.string.config_defaultRotationResolverService)); - } - @Override public int getRuntimePermissionsVersion(@UserIdInt int userId) { Preconditions.checkArgumentNonnegative(userId); @@ -5707,65 +4999,25 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mSettings.getDefaultRuntimePermissionsVersion(userId); } - @Nullable - @Override - public ServiceInfo getServiceInfo(@NonNull ComponentName component, - @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId) { - return mComputer.getServiceInfo(component, flags, userId); - } - - @Override - public @NonNull String getServicesSystemSharedLibraryPackageName() { - return mServicesExtensionPackageName; - } - - @Override - public String getSetupWizardPackageName() { - if (Binder.getCallingUid() != Process.SYSTEM_UID) { - throw new SecurityException("Non-system caller"); - } - return mPmInternal.getSetupWizardPackageName(); - } - - @Override - public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(String packageName, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - return mComputer.getSharedLibraries(packageName, flags, userId); - } - - @Override - public @NonNull String getSharedSystemSharedLibraryPackageName() { - return mSharedSystemSharedLibraryPackageName; - } - - @Nullable - @Override - public KeySet getSigningKeySet(@NonNull String packageName) { - return mComputer.getSigningKeySet(packageName); - } - @Override public String getSplashScreenTheme(@NonNull String packageName, int userId) { - PackageStateInternal packageState = - getPackageStateInstalledFiltered(packageName, Binder.getCallingUid(), userId); + final Computer snapshot = snapshotComputer(); + PackageStateInternal packageState = filterPackageStateForInstalledAndFiltered(snapshot, + packageName, Binder.getCallingUid(), userId); return packageState == null ? null : packageState.getUserStateOrDefault(userId).getSplashScreenTheme(); } @Override - public String getSdkSandboxPackageName() { - return mRequiredSdkSandboxPackage; - } - - @Override public Bundle getSuspendedPackageAppExtras(String packageName, int userId) { final int callingUid = Binder.getCallingUid(); - if (getPackageUid(packageName, 0, userId) != callingUid) { + final Computer snapshot = snapshot(); + if (snapshot.getPackageUid(packageName, 0, userId) != callingUid) { throw new SecurityException("Calling package " + packageName + " does not belong to calling uid " + callingUid); } - return mSuspendPackageHelper.getSuspendedPackageAppExtras( - packageName, userId, callingUid); + return mSuspendPackageHelper + .getSuspendedPackageAppExtras(snapshot, packageName, userId, callingUid); } @Override @@ -5785,34 +5037,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public String getSystemCaptionsServicePackageName() { - return ensureSystemPackageName( - getPackageFromComponentString(R.string.config_defaultSystemCaptionsService)); - } - - @Nullable - @Override - public String[] getSystemSharedLibraryNames() { - return mComputer.getSystemSharedLibraryNames(); - } - - @Override - public String getSystemTextClassifierPackageName() { - return ensureSystemPackageName( - mContext.getString(R.string.config_defaultTextClassifierPackage)); - } - - @Override - public int getTargetSdkVersion(@NonNull String packageName) { - return mComputer.getTargetSdkVersion(packageName); - } - - @Override - public int getUidForSharedUser(@NonNull String sharedUserName) { - return mComputer.getUidForSharedUser(sharedUserName); - } - - @Override public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) { Objects.requireNonNull(packageNames, "packageNames cannot be null"); mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, @@ -5838,18 +5062,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public String getWellbeingPackageName() { - final long identity = Binder.clearCallingIdentity(); - try { - return CollectionUtils.firstOrNull( - mContext.getSystemService(RoleManager.class).getRoleHolders( - RoleManager.ROLE_SYSTEM_WELLBEING)); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override public void grantImplicitAccess(int recipientUid, @NonNull String visibleAuthority) { final Computer snapshot = snapshotComputer(); final int recipientUserId = UserHandle.getUserId(recipientUid); @@ -5864,38 +5076,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService false /*direct*/, false /* retainOnUpdate */); } - // NOTE: Can't remove due to unsupported app usage - @Override - public void grantRuntimePermission(String packageName, String permName, final int userId) { - // Because this is accessed via the package manager service AIDL, - // go through the permission manager service AIDL - mContext.getSystemService(PermissionManager.class) - .grantRuntimePermission(packageName, permName, UserHandle.of(userId)); - } - - @Override - public boolean hasSigningCertificate(@NonNull String packageName, @NonNull byte[] certificate, - @PackageManager.CertificateInputType int type) { - return mComputer.hasSigningCertificate(packageName, certificate, type); - } - - @Override - public boolean hasSystemFeature(String name, int version) { - return PackageManagerService.this.hasSystemFeature(name, version); - } - - @Override - public boolean hasSystemUidErrors() { - // allow instant applications - return false; - } - - @Override - public boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate, - @PackageManager.CertificateInputType int type) { - return mComputer.hasUidSigningCertificate(uid, certificate, type); - } - @Override public void holdLock(IBinder token, int durationMs) { mTestUtilityService.verifyHoldLockToken(token); @@ -5924,55 +5104,17 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean isDeviceUpgrading() { - return PackageManagerService.this.isDeviceUpgrading(); - } - - @Override - public boolean isFirstBoot() { - return PackageManagerService.this.isFirstBoot(); - } - - @Override - public boolean isInstantApp(String packageName, int userId) { - return mComputer.isInstantApp(packageName, userId); - } - - @Override - public boolean isOnlyCoreApps() { - return PackageManagerService.this.isOnlyCoreApps(); - } - - @Override - public boolean isPackageAvailable(String packageName, int userId) { - return mComputer.isPackageAvailable(packageName, userId); - } - - @Override - public boolean isPackageDeviceAdminOnAnyUser(String packageName) { - return PackageManagerService.this.isPackageDeviceAdminOnAnyUser(packageName); - } - - @Override - public boolean isPackageSignedByKeySet(@NonNull String packageName, @NonNull KeySet ks) { - return mComputer.isPackageSignedByKeySet(packageName, ks); - } - - @Override - public boolean isPackageSignedByKeySetExactly(@NonNull String packageName, @NonNull KeySet ks) { - return mComputer.isPackageSignedByKeySetExactly(packageName, ks); - } - - @Override public boolean isPackageStateProtected(@NonNull String packageName, @UserIdInt int userId) { final int callingUid = Binder.getCallingUid(); final int callingAppId = UserHandle.getAppId(callingUid); - enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, true /*checkShell*/, "isPackageStateProtected"); if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.ROOT_UID - && checkUidPermission(MANAGE_DEVICE_ADMINS, callingUid) != PERMISSION_GRANTED) { + && snapshot.checkUidPermission(MANAGE_DEVICE_ADMINS, callingUid) + != PERMISSION_GRANTED) { throw new SecurityException("Caller must have the " + MANAGE_DEVICE_ADMINS + " permission."); } @@ -5981,11 +5123,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean isPackageSuspendedForUser(@NonNull String packageName, @UserIdInt int userId) { - return mComputer.isPackageSuspendedForUser(packageName, userId); - } - - @Override public boolean isProtectedBroadcast(String actionName) { if (actionName != null) { // TODO: remove these terrible hacks @@ -6002,22 +5139,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - @Override - public boolean isSafeMode() { - // allow instant applications - return mSafeMode; - } - - @Override - public boolean isStorageLow() { - return PackageManagerService.this.isStorageLow(); - } - - @Override - public boolean isUidPrivileged(int uid) { - return mComputer.isUidPrivileged(uid); - } - /** * Logs process start information (including base APK hash) to the security log. * @hide @@ -6025,13 +5146,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public void logAppProcessStartIfNeeded(String packageName, String processName, int uid, String seinfo, String apkFile, int pid) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { + final Computer snapshot = snapshotComputer(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { return; } if (!SecurityLog.isLoggingEnabled()) { return; } - mProcessLoggingHandler.logAppProcessStart(mContext, mPmInternal, apkFile, packageName, + mProcessLoggingHandler.logAppProcessStart(mContext, + LocalServices.getService(PackageManagerInternal.class), apkFile, packageName, processName, uid, seinfo, pid); } @@ -6083,25 +5206,29 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void notifyDexLoad(String loadingPackageName, Map<String, String> classLoaderContextMap, + public void notifyDexLoad(String loadingPackageName, + Map<String, String> classLoaderContextMap, String loaderIsa) { int callingUid = Binder.getCallingUid(); - if (PackageManagerService.PLATFORM_PACKAGE_NAME.equals(loadingPackageName) && callingUid != Process.SYSTEM_UID) { - Slog.w(PackageManagerService.TAG, "Non System Server process reporting dex loads as system server. uid=" - + callingUid); + if (PackageManagerService.PLATFORM_PACKAGE_NAME.equals(loadingPackageName) + && callingUid != Process.SYSTEM_UID) { + Slog.w(PackageManagerService.TAG, + "Non System Server process reporting dex loads as system server. uid=" + + callingUid); // Do not record dex loads from processes pretending to be system server. // Only the system server should be assigned the package "android", so reject calls // that don't satisfy the constraint. // // notifyDexLoad is a PM API callable from the app process. So in theory, apps could - // craft calls to this API and pretend to be system server. Doing so poses no particular - // danger for dex load reporting or later dexopt, however it is a sensible check to do - // in order to verify the expectations. + // craft calls to this API and pretend to be system server. Doing so poses no + // particular danger for dex load reporting or later dexopt, however it is a + // sensible check to do in order to verify the expectations. return; } int userId = UserHandle.getCallingUserId(); - ApplicationInfo ai = getApplicationInfo(loadingPackageName, /*flags*/ 0, userId); + ApplicationInfo ai = snapshot().getApplicationInfo(loadingPackageName, /*flags*/ 0, + userId); if (ai == null) { Slog.w(PackageManagerService.TAG, "Loading a package that does not exist for the calling user. package=" + loadingPackageName + ", user=" + userId); @@ -6115,11 +5242,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService public void notifyPackageUse(String packageName, int reason) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); + Computer snapshot = snapshotComputer(); final boolean notify; - if (getInstantAppPackageName(callingUid) != null) { - notify = isCallerSameApp(packageName, callingUid); + if (snapshot.getInstantAppPackageName(callingUid) != null) { + notify = snapshot.isCallerSameApp(packageName, callingUid); } else { - notify = !isInstantAppInternal(packageName, callingUserId, Process.SYSTEM_UID); + notify = !snapshot.isInstantAppInternal(packageName, callingUserId, + Process.SYSTEM_UID); } if (!notify) { return; @@ -6137,102 +5266,18 @@ public class PackageManagerService implements PackageSender, TestUtilityService updateComponentLabelIcon(componentName, nonLocalizedLabel, icon, userId); } - /** - * Ask the package manager to perform a dex-opt with the given compiler filter. - * - * Note: exposed only for the shell command to allow moving packages explicitly to a - * definite state. - */ - @Override - public boolean performDexOptMode(String packageName, - boolean checkProfiles, String targetCompilerFilter, boolean force, - boolean bootComplete, String splitName) { - return mDexOptHelper.performDexOptMode(packageName, checkProfiles, targetCompilerFilter, - force, bootComplete, splitName); - } - - /** - * Ask the package manager to perform a dex-opt with the given compiler filter on the - * secondary dex files belonging to the given package. - * - * Note: exposed only for the shell command to allow moving packages explicitly to a - * definite state. - */ - @Override - public boolean performDexOptSecondary(String packageName, String compilerFilter, - boolean force) { - return mDexOptHelper.performDexOptSecondary(packageName, compilerFilter, force); - } - - @NonNull - @Override - public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName, - int uid, @PackageManager.ComponentInfoFlagsBits long flags, - @Nullable String metaDataKey) { - return mComputer.queryContentProviders(processName, uid, flags, metaDataKey); - } - - @NonNull - @Override - public ParceledListSlice<InstrumentationInfo> queryInstrumentation( - @NonNull String targetPackage, int flags) { - return mComputer.queryInstrumentation(targetPackage, flags); - } - - @Override - public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - try { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities"); - - return new ParceledListSlice<>(snapshotComputer().queryIntentActivitiesInternal(intent, - resolvedType, flags, userId)); - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - } - - @Override - public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller, - Intent[] specifics, String[] specificTypes, Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - return new ParceledListSlice<>(mResolveIntentHelper.queryIntentActivityOptionsInternal( - snapshotComputer(), caller, specifics, specificTypes, intent, resolvedType, flags, - userId)); - } - - @Override - public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - return new ParceledListSlice<>(mResolveIntentHelper.queryIntentContentProvidersInternal( - snapshotComputer(), intent, resolvedType, flags, userId)); - } - - @Override - public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - return new ParceledListSlice<>(mResolveIntentHelper.queryIntentReceiversInternal( - snapshotComputer(), intent, resolvedType, flags, userId, Binder.getCallingUid())); - } - - @Override - public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - final int callingUid = Binder.getCallingUid(); - return new ParceledListSlice<>(snapshotComputer().queryIntentServicesInternal( - intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/)); - } - @Override public ParceledListSlice<PackageManager.Property> queryProperty( String propertyName, @PackageManager.PropertyLocation int componentType) { Objects.requireNonNull(propertyName); final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getCallingUserId(); + final Computer snapshot = snapshotComputer(); final List<PackageManager.Property> result = mPackageProperty.queryProperty(propertyName, componentType, packageName -> { - final PackageStateInternal ps = getPackageStateInternal(packageName); - return shouldFilterApplication(ps, callingUid, callingUserId); + final PackageStateInternal ps = + snapshot.getPackageStateInternal(packageName); + return snapshot.shouldFilterApplication(ps, callingUid, callingUserId); }); if (result == null) { return ParceledListSlice.emptyList(); @@ -6240,11 +5285,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return new ParceledListSlice<>(result); } - @Deprecated - public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) { - mComputer.querySyncProviders(mSafeMode, outNames, outInfo); - } - /** * Reconcile the information we have about the secondary dex files belonging to * {@code packageName} and the actual dex files. For all dex files that were @@ -6252,9 +5292,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService */ @Override public void reconcileSecondaryDexFiles(String packageName) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { + final Computer snapshot = snapshotComputer(); + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { return; - } else if (isInstantAppInternal( + } else if (snapshot.isInstantAppInternal( packageName, UserHandle.getCallingUserId(), Process.SYSTEM_UID)) { return; } @@ -6262,14 +5303,16 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void registerDexModule(String packageName, String dexModulePath, boolean isSharedModule, + public void registerDexModule(String packageName, String dexModulePath, + boolean isSharedModule, IDexModuleRegisterCallback callback) { int userId = UserHandle.getCallingUserId(); - ApplicationInfo ai = getApplicationInfo(packageName, /*flags*/ 0, userId); + ApplicationInfo ai = snapshot().getApplicationInfo(packageName, /*flags*/ 0, userId); DexManager.RegisterDexModuleResult result; if (ai == null) { - Slog.w(PackageManagerService.TAG, "Registering a dex module for a package that does not exist for the" + - " calling user. package=" + packageName + ", user=" + userId); + Slog.w(PackageManagerService.TAG, + "Registering a dex module for a package that does not exist for the" + + " calling user. package=" + packageName + ", user=" + userId); result = new DexManager.RegisterDexModuleResult(false, "Package not installed"); } else { result = mDexManager.registerDexModule(ai, dexModulePath, isSharedModule, userId); @@ -6278,9 +5321,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService if (callback != null) { mHandler.post(() -> { try { - callback.onDexModuleRegistered(dexModulePath, result.success, result.message); + callback.onDexModuleRegistered(dexModulePath, result.success, + result.message); } catch (RemoteException e) { - Slog.w(PackageManagerService.TAG, "Failed to callback after module registration " + dexModulePath, e); + Slog.w(PackageManagerService.TAG, + "Failed to callback after module registration " + dexModulePath, e); } }); } @@ -6293,52 +5338,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mMoveCallbacks.register(callback); } - // NOTE: Can't remove due to unsupported app usage - @Override - public void removePermission(String permName) { - // Because this is accessed via the package manager service AIDL, - // go through the permission manager service AIDL - mContext.getSystemService(PermissionManager.class).removePermission(permName); - } - - @Override - public void replacePreferredActivity(IntentFilter filter, int match, - ComponentName[] set, ComponentName activity, int userId) { - mPreferredActivityHelper.replacePreferredActivity(new WatchedIntentFilter(filter), - match, set, activity, userId); - } - - @Override - public void resetApplicationPreferences(int userId) { - mPreferredActivityHelper.resetApplicationPreferences(userId); - } - - @Override - public ProviderInfo resolveContentProvider(String name, - @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - return mComputer.resolveContentProvider(name, flags, userId, Binder.getCallingUid()); - } - - @Override - public ResolveInfo resolveIntent(Intent intent, String resolvedType, - @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - return mResolveIntentHelper.resolveIntentInternal(snapshotComputer(), intent, resolvedType, - flags, 0 /*privateResolveFlags*/, userId, false, Binder.getCallingUid()); - } - - @Override - public ResolveInfo resolveService(Intent intent, String resolvedType, - @PackageManager.ResolveInfoFlagsBits long flags, int userId) { - final int callingUid = Binder.getCallingUid(); - return mResolveIntentHelper.resolveServiceInternal(snapshotComputer(), intent, resolvedType, - flags, userId, callingUid); - } - - @Override - public void restoreDefaultApps(byte[] backup, int userId) { - mPreferredActivityHelper.restoreDefaultApps(backup, userId); - } - @Override public void restoreDomainVerification(byte[] backup, int userId) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { @@ -6366,11 +5365,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void restorePreferredActivities(byte[] backup, int userId) { - mPreferredActivityHelper.restorePreferredActivities(backup, userId); - } - - @Override public void sendDeviceCustomizationReadyBroadcast() { mContext.enforceCallingPermission(Manifest.permission.SEND_DEVICE_CUSTOMIZATION_READY, "sendDeviceCustomizationReadyBroadcast"); @@ -6386,16 +5380,17 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public void setApplicationCategoryHint(String packageName, int categoryHint, String callerPackageName) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - throw new SecurityException("Instant applications don't have access to this method"); - } - mInjector.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(), - callerPackageName); - final PackageStateMutator.InitialState initialState = recordInitialState(); final FunctionalUtils.ThrowingFunction<Computer, PackageStateMutator.Result> implementation = computer -> { + if (computer.getInstantAppPackageName(Binder.getCallingUid()) != null) { + throw new SecurityException( + "Instant applications don't have access to this method"); + } + mInjector.getSystemService(AppOpsManager.class) + .checkPackage(Binder.getCallingUid(), callerPackageName); + PackageStateInternal packageState = computer.getPackageStateFiltered(packageName, Binder.getCallingUid(), UserHandle.getCallingUserId()); if (packageState == null) { @@ -6447,7 +5442,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, true /* checkShell */, "setApplicationHiddenSetting for user " + userId); if (hidden && isPackageDeviceAdmin(packageName, userId)) { @@ -6464,7 +5460,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService final long callingId = Binder.clearCallingIdentity(); try { final PackageStateInternal packageState = - mComputer.getPackageStateFiltered(packageName, callingUid, userId); + snapshot.getPackageStateFiltered(packageName, callingUid, userId); if (packageState == null) { return false; } @@ -6505,13 +5501,16 @@ public class PackageManagerService implements PackageSender, TestUtilityService commitPackageStateMutation(null, packageName, packageState1 -> packageState1.userState(userId).setHidden(hidden)); - final PackageStateInternal newPackageState = getPackageStateInternal(packageName); + final Computer newSnapshot = snapshotComputer(); + final PackageStateInternal newPackageState = + newSnapshot.getPackageStateInternal(packageName); if (hidden) { killApplication(packageName, newPackageState.getAppId(), userId, "hiding pkg"); sendApplicationHiddenForUser(packageName, newPackageState, userId); } else { - sendPackageAddedForUser(packageName, newPackageState, userId, DataLoaderType.NONE); + sendPackageAddedForUser(newSnapshot, packageName, newPackageState, userId, + DataLoaderType.NONE); } scheduleWritePackageRestrictions(userId); @@ -6526,7 +5525,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService int userId) { mContext.enforceCallingOrSelfPermission( Manifest.permission.DELETE_PACKAGES, null); - PackageStateInternal packageState = getPackageStateInternal(packageName); + final Computer snapshot = snapshotComputer(); + PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState != null && packageState.getPkg() != null) { AndroidPackage pkg = packageState.getPkg(); // Cannot block uninstall SDK libs as they are controlled by SDK manager. @@ -6584,8 +5584,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService + userId); } Objects.requireNonNull(packageNames, "packageNames cannot be null"); + final Computer snapshot = snapshotComputer(); if (restrictionFlags != 0 - && !mSuspendPackageHelper.isSuspendAllowedForUser(userId, callingUid)) { + && !mSuspendPackageHelper.isSuspendAllowedForUser(snapshot, userId, + callingUid)) { Slog.w(PackageManagerService.TAG, "Cannot restrict packages due to restrictions on user " + userId); return packageNames; } @@ -6595,16 +5597,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService final List<String> unactionedPackages = new ArrayList<>(packageNames.length); ArraySet<String> changesToCommit = new ArraySet<>(); - Computer computer = snapshotComputer(); final boolean[] canRestrict = (restrictionFlags != 0) - ? mSuspendPackageHelper.canSuspendPackageForUser(computer, packageNames, userId, + ? mSuspendPackageHelper.canSuspendPackageForUser(snapshot, packageNames, userId, callingUid) : null; for (int i = 0; i < packageNames.length; i++) { final String packageName = packageNames[i]; final PackageStateInternal packageState = - computer.getPackageStateInternal(packageName); + snapshot.getPackageStateInternal(packageName); if (packageState == null - || computer.shouldFilterApplication(packageState, callingUid, userId)) { + || snapshot.shouldFilterApplication(packageState, callingUid, userId)) { Slog.w(PackageManagerService.TAG, "Could not find package setting for package: " + packageName + ". Skipping..."); unactionedPackages.add(packageName); @@ -6648,11 +5649,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService final int callingUid = Binder.getCallingUid(); final int callingAppId = UserHandle.getAppId(callingUid); - enforceCrossUserPermission(callingUid, userId, true /*requireFullPermission*/, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, true /*requireFullPermission*/, true /*checkShell*/, "setHarmfulAppInfo"); if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.ROOT_UID && - checkUidPermission(SET_HARMFUL_APP_WARNINGS, callingUid) != PERMISSION_GRANTED) { + snapshot.checkUidPermission(SET_HARMFUL_APP_WARNINGS, callingUid) + != PERMISSION_GRANTED) { throw new SecurityException("Caller must have the " + SET_HARMFUL_APP_WARNINGS + " permission."); } @@ -6667,11 +5670,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void setHomeActivity(ComponentName comp, int userId) { - mPreferredActivityHelper.setHomeActivity(comp, userId); - } - - @Override public boolean setInstallLocation(int loc) { mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null); @@ -6693,24 +5691,24 @@ public class PackageManagerService implements PackageSender, TestUtilityService final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); final FunctionalUtils.ThrowingCheckedFunction<Computer, Boolean, RuntimeException> - implementation = computer -> { - if (computer.getInstantAppPackageName(callingUid) != null) { + implementation = snapshot -> { + if (snapshot.getInstantAppPackageName(callingUid) != null) { return false; } PackageStateInternal targetPackageState = - computer.getPackageStateInternal(targetPackage); + snapshot.getPackageStateInternal(targetPackage); if (targetPackageState == null - || computer.shouldFilterApplication(targetPackageState, callingUid, + || snapshot.shouldFilterApplication(targetPackageState, callingUid, callingUserId)) { throw new IllegalArgumentException("Unknown target package: " + targetPackage); } PackageStateInternal installerPackageState = null; if (installerPackageName != null) { - installerPackageState = computer.getPackageStateInternal(installerPackageName); + installerPackageState = snapshot.getPackageStateInternal(installerPackageName); if (installerPackageState == null - || shouldFilterApplication( + || snapshot.shouldFilterApplication( installerPackageState, callingUid, callingUserId)) { throw new IllegalArgumentException("Unknown installer package: " + installerPackageName); @@ -6720,7 +5718,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService Signature[] callerSignature; final int appId = UserHandle.getAppId(callingUid); Pair<PackageStateInternal, SharedUserApi> either = - computer.getPackageOrSharedUser(appId); + snapshot.getPackageOrSharedUser(appId); if (either != null) { if (either.first != null) { callerSignature = either.first.getSigningDetails().getSignatures(); @@ -6748,7 +5746,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService String targetInstallerPackageName = targetPackageState.getInstallSource().installerPackageName; PackageStateInternal targetInstallerPkgSetting = targetInstallerPackageName == null - ? null : computer.getPackageStateInternal(targetInstallerPackageName); + ? null : snapshot.getPackageStateInternal(targetInstallerPackageName); if (targetInstallerPkgSetting != null) { if (compareSignatures(callerSignature, @@ -6804,7 +5802,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } } - targetPackageState = getPackageStateInternal(targetPackage); + targetPackageState = snapshotComputer().getPackageStateInternal(targetPackage); mSettings.addInstallerPackageNames(targetPackageState.getInstallSource()); } mAppsFilter.addPackage(targetPackageState); @@ -6818,14 +5816,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService return true; } - enforceCrossUserPermission(Binder.getCallingUid(), userId, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, true /* checkShell */, "setInstantAppCookie"); - if (!isCallerSameApp(packageName, Binder.getCallingUid())) { + if (!snapshot.isCallerSameApp(packageName, Binder.getCallingUid())) { return false; } - PackageStateInternal packageState = getPackageStateInternal(packageName); + PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState == null || packageState.getPkg() == null) { return false; } @@ -6840,21 +5839,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService "setKeepUninstalledPackages requires KEEP_UNINSTALLED_PACKAGES permission"); Objects.requireNonNull(packageList); - setKeepUninstalledPackagesInternal(packageList); - } - - @Override - public void setLastChosenActivity(Intent intent, String resolvedType, int flags, - IntentFilter filter, int match, ComponentName activity) { - mPreferredActivityHelper.setLastChosenActivity(intent, resolvedType, flags, - new WatchedIntentFilter(filter), match, activity); + setKeepUninstalledPackagesInternal(snapshot(), packageList); } @Override public void setMimeGroup(String packageName, String mimeGroup, List<String> mimeTypes) { - enforceOwnerRights(packageName, Binder.getCallingUid()); + final Computer snapshot = snapshotComputer(); + enforceOwnerRights(snapshot, packageName, Binder.getCallingUid()); mimeTypes = CollectionUtils.emptyIfNull(mimeTypes); - final PackageStateInternal packageState = getPackageStateInternal(packageName); + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); Set<String> existingMimeTypes = packageState.getMimeGroups().get(mimeGroup); if (existingMimeTypes == null) { throw new IllegalArgumentException("Unknown MIME group " + mimeGroup @@ -6889,11 +5882,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService PersistableBundle appExtras, PersistableBundle launcherExtras, SuspendDialogInfo dialogInfo, String callingPackage, int userId) { final int callingUid = Binder.getCallingUid(); - enforceCanSetPackagesSuspendedAsUser(callingPackage, callingUid, userId, + final Computer snapshot = snapshotComputer(); + enforceCanSetPackagesSuspendedAsUser(snapshot, callingPackage, callingUid, userId, "setPackagesSuspendedAsUser"); - return mSuspendPackageHelper.setPackagesSuspended(snapshotComputer(), packageNames, - suspended, appExtras, launcherExtras, dialogInfo, callingPackage, userId, - callingUid); + return mSuspendPackageHelper.setPackagesSuspended(snapshot, packageNames, suspended, + appExtras, launcherExtras, dialogInfo, callingPackage, userId, callingUid); } @Override @@ -6924,12 +5917,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService public void setSplashScreenTheme(@NonNull String packageName, @Nullable String themeId, int userId) { final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "setSplashScreenTheme"); - enforceOwnerRights(packageName, callingUid); + enforceOwnerRights(snapshot, packageName, callingUid); - PackageStateInternal packageState = getPackageStateInstalledFiltered(packageName, - callingUid, userId); + PackageStateInternal packageState = filterPackageStateForInstalledAndFiltered(snapshot, + packageName, callingUid, userId); if (packageState == null) { return; } @@ -6939,80 +5933,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden) { - final int callingUid = Binder.getCallingUid(); - final boolean calledFromSystemOrPhone = callingUid == Process.PHONE_UID - || callingUid == Process.SYSTEM_UID; - if (!calledFromSystemOrPhone) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, - "setSystemAppHiddenUntilInstalled"); - } - - final PackageStateInternal stateRead = getPackageStateInternal(packageName); - if (stateRead == null || !stateRead.isSystem() || stateRead.getPkg() == null) { - return; - } - if (stateRead.getPkg().isCoreApp() && !calledFromSystemOrPhone) { - throw new SecurityException("Only system or phone callers can modify core apps"); - } - - commitPackageStateMutation(null, mutator -> { - mutator.forPackage(packageName) - .setHiddenUntilInstalled(hidden); - mutator.forDisabledSystemPackage(packageName) - .setHiddenUntilInstalled(hidden); - }); - } - - @Override - public boolean setSystemAppInstallState(String packageName, boolean installed, int userId) { - final int callingUid = Binder.getCallingUid(); - final boolean calledFromSystemOrPhone = callingUid == Process.PHONE_UID - || callingUid == Process.SYSTEM_UID; - if (!calledFromSystemOrPhone) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, - "setSystemAppHiddenUntilInstalled"); - } - - final PackageStateInternal packageState = getPackageStateInternal(packageName); - // The target app should always be in system - if (packageState == null || !packageState.isSystem() || packageState.getPkg() == null) { - return false; - } - if (packageState.getPkg().isCoreApp() && !calledFromSystemOrPhone) { - throw new SecurityException("Only system or phone callers can modify core apps"); - } - // Check if the install state is the same - if (packageState.getUserStateOrDefault(userId).isInstalled() == installed) { - return false; - } - - final long callingId = Binder.clearCallingIdentity(); - try { - if (installed) { - // install the app from uninstalled state - installExistingPackageAsUser( - packageName, - userId, - PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, - PackageManager.INSTALL_REASON_DEVICE_SETUP, - null); - return true; - } - - // uninstall the app from installed state - deletePackageVersioned( - new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), - new PackageManager.LegacyPackageDeleteObserver(null).getBinder(), - userId, - PackageManager.DELETE_SYSTEM_APP); - return true; - } finally { - Binder.restoreCallingIdentity(callingId); - } - } - - @Override public void setUpdateAvailable(String packageName, boolean updateAvailable) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null); commitPackageStateMutation(null, packageName, state -> @@ -7026,19 +5946,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mMoveCallbacks.unregister(callback); } - @Deprecated - @Override - public boolean updateIntentVerificationStatus(String packageName, int status, int userId) { - return mDomainVerificationManager.setLegacyUserState(packageName, userId, status); - } - - @Deprecated - @Override - public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) { - DomainVerificationProxyV1.queueLegacyVerifyResult(mContext, mDomainVerificationConnection, - id, verificationCode, failedDomains, Binder.getCallingUid()); - } - @Override public void verifyPendingInstall(int id, int verificationCode) throws RemoteException { mContext.enforceCallingOrSelfPermission( @@ -7059,9 +5966,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Checksum.TypeMask int optional, @Checksum.TypeMask int required, @Nullable List trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId) { - requestChecksumsInternal(packageName, includeSplits, optional, required, trustedInstallers, - onChecksumsReadyListener, userId, mInjector.getBackgroundExecutor(), - mInjector.getBackgroundHandler()); + requestChecksumsInternal(snapshotComputer(), packageName, includeSplits, optional, + required, trustedInstallers, onChecksumsReadyListener, userId, + mInjector.getBackgroundExecutor(), mInjector.getBackgroundHandler()); } @Override @@ -7074,12 +5981,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean canPackageQuery(@NonNull String sourcePackageName, - @NonNull String targetPackageName, @UserIdInt int userId) { - return mComputer.canPackageQuery(sourcePackageName, targetPackageName, userId); - } - - @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { try { @@ -7097,8 +5998,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { - (new PackageManagerShellCommand(mIPackageManager, - mContext,mDomainVerificationManager.getShell())) + (new PackageManagerShellCommand(this, mContext, + mDomainVerificationManager.getShell())) .exec(this, in, out, err, args, callback, resultReceiver); } @@ -7113,143 +6014,126 @@ public class PackageManagerService implements PackageSender, TestUtilityService private class PackageManagerLocalImpl implements PackageManagerLocal { } - private class PackageManagerInternalImpl extends PackageManagerInternal { - @Override - public List<ApplicationInfo> getInstalledApplications( - @PackageManager.ApplicationInfoFlagsBits long flags, int userId, int callingUid) { - return PackageManagerService.this.mComputer.getInstalledApplications(flags, userId, - callingUid); - } + private class PackageManagerInternalImpl extends PackageManagerInternalBase { - @Override - public boolean isPlatformSigned(String packageName) { - PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState == null) { - return false; - } - SigningDetails signingDetails = packageState.getSigningDetails(); - return signingDetails.hasAncestorOrSelf(mPlatformPackage.getSigningDetails()) - || mPlatformPackage.getSigningDetails().checkCapability(signingDetails, - SigningDetails.CertCapabilities.PERMISSION); - } - - @Override - public boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName) { - SigningDetails sd = getSigningDetails(packageName); - if (sd == null) { - return false; - } - return sd.hasSha256Certificate(restoringFromSigHash, - SigningDetails.CertCapabilities.INSTALLED_DATA); - } - - @Override - public boolean isDataRestoreSafe(Signature restoringFromSig, String packageName) { - SigningDetails sd = getSigningDetails(packageName); - if (sd == null) { - return false; - } - return sd.hasCertificate(restoringFromSig, - SigningDetails.CertCapabilities.INSTALLED_DATA); + public PackageManagerInternalImpl() { + super(PackageManagerService.this); } + @NonNull @Override - public boolean hasSignatureCapability(int serverUid, int clientUid, - @SigningDetails.CertCapabilities int capability) { - SigningDetails serverSigningDetails = getSigningDetails(serverUid); - SigningDetails clientSigningDetails = getSigningDetails(clientUid); - return serverSigningDetails.checkCapability(clientSigningDetails, capability) - || clientSigningDetails.hasAncestorOrSelf(serverSigningDetails); - - } - - private SigningDetails getSigningDetails(@NonNull String packageName) { - return PackageManagerService.this.getSigningDetails(packageName); - } - - private SigningDetails getSigningDetails(int uid) { - return PackageManagerService.this.getSigningDetails(uid); + protected Context getContext() { + return mContext; } + @NonNull @Override - public boolean isInstantApp(String packageName, int userId) { - return PackageManagerService.this.mIPackageManager.isInstantApp(packageName, userId); + protected PermissionManagerServiceInternal getPermissionManager() { + return mPermissionManager; } + @NonNull @Override - public String getInstantAppPackageName(int uid) { - return PackageManagerService.this.getInstantAppPackageName(uid); + protected AppDataHelper getAppDataHelper() { + return mAppDataHelper; } + @NonNull @Override - public boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) { - return PackageManagerService.this.filterAppAccess(pkg, callingUid, userId); + protected PackageObserverHelper getPackageObserverHelper() { + return mPackageObserverHelper; } + @NonNull @Override - public boolean filterAppAccess(String packageName, int callingUid, int userId) { - return PackageManagerService.this.filterAppAccess(packageName, callingUid, userId); + protected ResolveIntentHelper getResolveIntentHelper() { + return mResolveIntentHelper; } + @NonNull @Override - public boolean filterAppAccess(int uid, int callingUid) { - return PackageManagerService.this.filterAppAccess(uid, callingUid); + protected SuspendPackageHelper getSuspendPackageHelper() { + return mSuspendPackageHelper; } - @Nullable + @NonNull @Override - public int[] getVisibilityAllowList(@NonNull String packageName, int userId) { - return PackageManagerService.this.getVisibilityAllowList(packageName, userId); + protected ProtectedPackages getProtectedPackages() { + return mProtectedPackages; } + @NonNull @Override - public boolean canQueryPackage(int callingUid, @Nullable String packageName) { - return PackageManagerService.this.canQueryPackage(callingUid, packageName); + protected UserNeedsBadgingCache getUserNeedsBadging() { + return mUserNeedsBadging; } + @NonNull @Override - public AndroidPackage getPackage(String packageName) { - return PackageManagerService.this.getPackage(packageName); + protected InstantAppRegistry getInstantAppRegistry() { + return mInstantAppRegistry; } - @Nullable + @NonNull @Override - public AndroidPackageApi getAndroidPackage(@NonNull String packageName) { - return PackageManagerService.this.getPackage(packageName); + protected ApexManager getApexManager() { + return mApexManager; } + @NonNull @Override - public AndroidPackage getPackage(int uid) { - return PackageManagerService.this.getPackage(uid); + protected DexManager getDexManager() { + return mDexManager; } @Override - public List<AndroidPackage> getPackagesForAppId(int appId) { - return mComputer.getPackagesForAppId(appId); + public boolean isPlatformSigned(String packageName) { + PackageStateInternal packageState = snapshot().getPackageStateInternal(packageName); + if (packageState == null) { + return false; + } + SigningDetails signingDetails = packageState.getSigningDetails(); + return signingDetails.hasAncestorOrSelf(mPlatformPackage.getSigningDetails()) + || mPlatformPackage.getSigningDetails().checkCapability(signingDetails, + SigningDetails.CertCapabilities.PERMISSION); } - @Nullable @Override - public PackageStateInternal getPackageStateInternal(String packageName) { - return PackageManagerService.this.getPackageStateInternal(packageName); + public boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName) { + final Computer snapshot = snapshot(); + SigningDetails sd = snapshot.getSigningDetails(packageName); + if (sd == null) { + return false; + } + return sd.hasSha256Certificate(restoringFromSigHash, + SigningDetails.CertCapabilities.INSTALLED_DATA); } - @Nullable @Override - public PackageState getPackageState(@NonNull String packageName) { - return PackageManagerService.this.getPackageState(packageName); + public boolean isDataRestoreSafe(Signature restoringFromSig, String packageName) { + final Computer snapshot = snapshot(); + SigningDetails sd = snapshot.getSigningDetails(packageName); + if (sd == null) { + return false; + } + return sd.hasCertificate(restoringFromSig, + SigningDetails.CertCapabilities.INSTALLED_DATA); } - @NonNull @Override - public ArrayMap<String, ? extends PackageStateInternal> getPackageStates() { - return PackageManagerService.this.getPackageStates(); + public boolean hasSignatureCapability(int serverUid, int clientUid, + @SigningDetails.CertCapabilities int capability) { + final Computer snapshot = snapshot(); + SigningDetails serverSigningDetails = snapshot.getSigningDetails(serverUid); + SigningDetails clientSigningDetails = snapshot.getSigningDetails(clientUid); + return serverSigningDetails.checkCapability(clientSigningDetails, capability) + || clientSigningDetails.hasAncestorOrSelf(serverSigningDetails); } @Override public PackageList getPackageList(@Nullable PackageListObserver observer) { final ArrayList<String> list = new ArrayList<>(); - forEachPackageState(packageState -> { + PackageManagerService.this.forEachPackageState(snapshot(), packageState -> { AndroidPackage pkg = packageState.getPkg(); if (pkg != null) { list.add(pkg.getPackageName()); @@ -7263,19 +6147,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void removePackageListObserver(PackageListObserver observer) { - mPackageObserverHelper.removeObserver(observer); - } - - @Override - public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) { - return snapshotComputer().getDisabledSystemPackage(packageName); - } - - @Override public @Nullable String getDisabledSystemPackageName(@NonNull String packageName) { - PackageStateInternal disabledPkgSetting = getDisabledSystemPackage( + PackageStateInternal disabledPkgSetting = snapshot().getDisabledSystemPackage( packageName); AndroidPackage disabledPkg = disabledPkgSetting == null ? null : disabledPkgSetting.getPkg(); @@ -7283,51 +6157,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) { - return PackageManagerService.this.getKnownPackageNamesInternal(knownPackage, userId); - } - - @Override - public boolean isSameApp(@Nullable String packageName, int callingUid, int userId) { - if (packageName == null) { - return false; - } - - if (Process.isSdkSandboxUid(callingUid)) { - return packageName.equals(getSdkSandboxPackageName()); - } - int uid = getPackageUid(packageName, 0, userId); - return UserHandle.isSameApp(uid, callingUid); - } - - @Override public boolean isResolveActivityComponent(ComponentInfo component) { return mResolveActivity.packageName.equals(component.packageName) && mResolveActivity.name.equals(component.name); } @Override - public void setKeepUninstalledPackages(final List<String> packageList) { - PackageManagerService.this.setKeepUninstalledPackagesInternal(packageList); - } - - @Override - public boolean isPermissionsReviewRequired(String packageName, int userId) { - return mPermissionManager.isPermissionsReviewRequired(packageName, userId); - } - - @Override - public PackageInfo getPackageInfo( - String packageName, @PackageManager.PackageInfoFlagsBits long flags, - int filterCallingUid, int userId) { - return PackageManagerService.this.mComputer - .getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST, - flags, filterCallingUid, userId); - } - - @Override public long getCeDataInode(String packageName, int userId) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); + final PackageStateInternal packageState = + snapshot().getPackageStateInternal(packageName); if (packageState == null) { return 0; } else { @@ -7336,18 +6174,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public Bundle getSuspendedPackageLauncherExtras(String packageName, int userId) { - return mSuspendPackageHelper.getSuspendedPackageLauncherExtras( - packageName, userId, Binder.getCallingUid()); - } - - @Override - public boolean isPackageSuspended(String packageName, int userId) { - return mSuspendPackageHelper.isPackageSuspended( - packageName, userId, Binder.getCallingUid()); - } - - @Override public void removeAllNonSystemPackageSuspensions(int userId) { final Computer computer = snapshotComputer(); final String[] allPackages = computer.getAllAvailablePackageNames(); @@ -7357,14 +6183,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void removeNonSystemPackageSuspensions(String packageName, int userId) { - mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(snapshotComputer(), - new String[]{packageName}, - (suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage), - userId); - } - - @Override public void flushPackageRestrictions(int userId) { synchronized (mLock) { PackageManagerService.this.flushPackageRestrictionsAsUserInternalLocked(userId); @@ -7372,103 +6190,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void removeDistractingPackageRestrictions(String packageName, int userId) { - PackageManagerService.this.removeDistractingPackageRestrictions( - new String[]{packageName}, userId); - } - - @Override - public void removeAllDistractingPackageRestrictions(int userId) { - PackageManagerService.this.removeAllDistractingPackageRestrictions(userId); - } - - @Override - public String getSuspendingPackage(String suspendedPackage, int userId) { - return mSuspendPackageHelper.getSuspendingPackage( - suspendedPackage, userId, Binder.getCallingUid()); - } - - @Override - public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, - String suspendingPackage, int userId) { - return mSuspendPackageHelper.getSuspendedDialogInfo( - suspendedPackage, suspendingPackage, userId, Binder.getCallingUid()); - } - - @Override - public int getDistractingPackageRestrictions(String packageName, int userId) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - return (packageState == null) ? RESTRICTION_NONE - : packageState.getUserStateOrDefault(userId).getDistractionFlags(); - } - - @Override - public int getPackageUid(String packageName, - @PackageManager.PackageInfoFlagsBits long flags, int userId) { - return PackageManagerService.this - .getPackageUidInternal(packageName, flags, userId, Process.SYSTEM_UID); - } - - @Override - public ApplicationInfo getApplicationInfo( - String packageName, @PackageManager.ApplicationInfoFlagsBits long flags, - int filterCallingUid, int userId) { - return PackageManagerService.this - .getApplicationInfoInternal(packageName, flags, filterCallingUid, userId); - } - - @Override - public ActivityInfo getActivityInfo( - ComponentName component, @PackageManager.ComponentInfoFlagsBits long flags, - int filterCallingUid, int userId) { - return PackageManagerService.this - .getActivityInfoInternal(component, flags, filterCallingUid, userId); - } - - @Override - public List<ResolveInfo> queryIntentActivities( - Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - int filterCallingUid, int userId) { - return snapshotComputer().queryIntentActivitiesInternal(intent, resolvedType, flags, - userId); - } - - @Override - public List<ResolveInfo> queryIntentReceivers(Intent intent, - String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, - int filterCallingUid, int userId) { - return PackageManagerService.this.mResolveIntentHelper.queryIntentReceiversInternal( - snapshotComputer(), intent, resolvedType, flags, userId, filterCallingUid); - } - - @Override - public List<ResolveInfo> queryIntentServices( - Intent intent, @PackageManager.ResolveInfoFlagsBits long flags, int callingUid, - int userId) { - final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver()); - return PackageManagerService.this - .queryIntentServicesInternal(intent, resolvedType, flags, userId, callingUid, - false); - } - - @Override - public ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, - int userId) { - return PackageManagerService.this.getHomeActivitiesAsUser(allHomeCandidates, userId); - } - - @Override - public ComponentName getDefaultHomeActivity(int userId) { - return PackageManagerService.this.getDefaultHomeActivity(userId); - } - - @Override - public ComponentName getSystemUiServiceComponent() { - return ComponentName.unflattenFromString(mContext.getResources().getString( - com.android.internal.R.string.config_systemUIServiceComponent)); - } - - @Override public void setDeviceAndProfileOwnerPackages( int deviceOwnerUserId, String deviceOwnerPackage, SparseArray<String> profileOwnerPackages) { @@ -7487,118 +6208,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void setDeviceOwnerProtectedPackages( - String deviceOwnerPackageName, List<String> packageNames) { - mProtectedPackages.setDeviceOwnerProtectedPackages( - deviceOwnerPackageName, packageNames); - } - - @Override - public boolean isPackageDataProtected(int userId, String packageName) { - return mProtectedPackages.isPackageDataProtected(userId, packageName); - } - - @Override - public boolean isPackageStateProtected(String packageName, int userId) { - return mProtectedPackages.isPackageStateProtected(userId, packageName); - } - - @Override - public boolean isPackageEphemeral(int userId, String packageName) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - return packageState != null - && packageState.getUserStateOrDefault(userId).isInstantApp(); - } - - @Override - public boolean wasPackageEverLaunched(String packageName, int userId) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - return !packageState.getUserStateOrDefault(userId).isNotLaunched(); - } - - @Override - public boolean isEnabledAndMatches(ParsedMainComponent component, long flags, int userId) { - return PackageStateUtils.isEnabledAndMatches( - getPackageStateInternal(component.getPackageName()), component, flags, userId); - } - - @Override - public boolean userNeedsBadging(int userId) { - synchronized (mLock) { - return PackageManagerService.this.userNeedsBadging(userId); - } - } - - @Override - public String getNameForUid(int uid) { - return mIPackageManager.getNameForUid(uid); - } - - @Override - public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, - Intent origIntent, String resolvedType, String callingPackage, - @Nullable String callingFeatureId, boolean isRequesterInstantApp, - Bundle verificationBundle, int userId) { - PackageManagerService.this.requestInstantAppResolutionPhaseTwo(responseObj, origIntent, - resolvedType, callingPackage, callingFeatureId, isRequesterInstantApp, - verificationBundle, userId); - } - - @Override - public void grantImplicitAccess(int userId, Intent intent, - int recipientAppId, int visibleUid, boolean direct) { - grantImplicitAccess(userId, intent, recipientAppId, visibleUid, direct, - false /* retainOnUpdate */); - } - - @Override - public void grantImplicitAccess(int userId, Intent intent, - int recipientAppId, int visibleUid, boolean direct, boolean retainOnUpdate) { - Computer computer = snapshotComputer(); - final AndroidPackage visiblePackage = computer.getPackage(visibleUid); - final int recipientUid = UserHandle.getUid(userId, recipientAppId); - if (visiblePackage == null || computer.getPackage(recipientUid) == null) { - return; - } - - final boolean instantApp = computer.isInstantAppInternal( - visiblePackage.getPackageName(), userId, visibleUid); - final boolean accessGranted; - if (instantApp) { - if (!direct) { - // if the interaction that lead to this granting access to an instant app - // was indirect (i.e.: URI permission grant), do not actually execute the - // grant. - return; - } - accessGranted = mInstantAppRegistry.grantInstantAccess(userId, intent, - recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/); - } else { - accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid, - retainOnUpdate); - } - - if (accessGranted) { - ApplicationPackageManager.invalidateGetPackagesForUidCache(); - } - } - - @Override - public boolean isInstantAppInstallerComponent(ComponentName component) { - final ActivityInfo instantAppInstallerActivity = mInstantAppInstallerActivity; - return instantAppInstallerActivity != null - && instantAppInstallerActivity.getComponentName().equals(component); - } - - @Override - public void pruneInstantApps() { - mInstantAppRegistry.pruneInstantApps(snapshotComputer()); - } - - @Override public void pruneCachedApksInApex(@NonNull List<PackageInfo> apexPackages) { if (mCacheDir == null) { return; @@ -7606,11 +6215,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService final PackageCacher cacher = new PackageCacher(mCacheDir); synchronized (mLock) { + final Computer snapshot = snapshot(); for (int i = 0, size = apexPackages.size(); i < size; i++) { final List<String> apkNames = mApexManager.getApksInApex(apexPackages.get(i).packageName); for (int j = 0, apksInApex = apkNames.size(); j < apksInApex; j++) { - final AndroidPackage pkg = getPackage(apkNames.get(j)); + final AndroidPackage pkg = snapshot.getPackage(apkNames.get(j)); cacher.cleanCachedResult(new File(pkg.getPath())); } } @@ -7618,10 +6228,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public String getSetupWizardPackageName() { - return mSetupWizardPackage; - } - public void setExternalSourcesPolicy(ExternalSourcesPolicy policy) { if (policy != null) { mExternalSourcesPolicy = policy; @@ -7630,7 +6236,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public boolean isPackagePersistent(String packageName) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); + final PackageStateInternal packageState = + snapshot().getPackageStateInternal(packageName); if (packageState == null) { return false; } @@ -7641,16 +6248,20 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public List<PackageInfo> getOverlayPackages(int userId) { + final Computer snapshot = snapshotComputer(); final ArrayList<PackageInfo> overlayPackages = new ArrayList<>(); - forEachPackageState(packageState -> { + final ArrayMap<String, ? extends PackageStateInternal> packageStates = + snapshot.getPackageStates(); + for (int index = 0; index < packageStates.size(); index++) { + final PackageStateInternal packageState = packageStates.valueAt(index); final AndroidPackage pkg = packageState.getPkg(); if (pkg != null && pkg.getOverlayTarget() != null) { - PackageInfo pkgInfo = generatePackageInfo(packageState, 0, userId); + PackageInfo pkgInfo = snapshot.generatePackageInfo(packageState, 0, userId); if (pkgInfo != null) { overlayPackages.add(pkgInfo); } } - }); + } return overlayPackages; } @@ -7658,7 +6269,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public List<String> getTargetPackageNames(int userId) { List<String> targetPackages = new ArrayList<>(); - forEachPackageState(packageState -> { + PackageManagerService.this.forEachPackageState(snapshot(), packageState -> { final AndroidPackage pkg = packageState.getPkg(); if (pkg != null && !pkg.isOverlay()) { targetPackages.add(pkg.getPackageName()); @@ -7676,30 +6287,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public ResolveInfo resolveIntent(Intent intent, String resolvedType, - @PackageManager.ResolveInfoFlagsBits long flags, - @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, - boolean resolveForStart, int filterCallingUid) { - return mResolveIntentHelper.resolveIntentInternal(snapshotComputer(), - intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart, - filterCallingUid); - } - - @Override - public ResolveInfo resolveService(Intent intent, String resolvedType, - @PackageManager.ResolveInfoFlagsBits long flags, int userId, int callingUid) { - return mResolveIntentHelper.resolveServiceInternal(snapshotComputer(), intent, - resolvedType, flags, userId, callingUid); - } - - @Override - public ProviderInfo resolveContentProvider(String name, - @PackageManager.ResolveInfoFlagsBits long flags, int userId, int callingUid) { - return PackageManagerService.this.mComputer - .resolveContentProvider(name, flags, userId,callingUid); - } - - @Override public void addIsolatedUid(int isolatedUid, int ownerUid) { synchronized (mLock) { mIsolatedOwners.put(isolatedUid, ownerUid); @@ -7714,146 +6301,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public int getUidTargetSdkVersion(int uid) { - return PackageManagerService.this.getUidTargetSdkVersion(uid); - } - - @Override - public int getPackageTargetSdkVersion(String packageName) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState != null && packageState.getPkg() != null) { - return packageState.getPkg().getTargetSdkVersion(); - } - return Build.VERSION_CODES.CUR_DEVELOPMENT; - } - - @Override - public boolean canAccessInstantApps(int callingUid, int userId) { - return PackageManagerService.this.canViewInstantApps(callingUid, userId); - } - - @Override - public boolean canAccessComponent(int callingUid, @NonNull ComponentName component, - @UserIdInt int userId) { - return mComputer.canAccessComponent(callingUid, component, userId); - } - - @Override - public boolean hasInstantApplicationMetadata(String packageName, int userId) { - return mInstantAppRegistry.hasInstantApplicationMetadata(packageName, userId); - } - - @Override public void notifyPackageUse(String packageName, int reason) { synchronized (mLock) { PackageManagerService.this.notifyPackageUseInternal(packageName, reason); } } - @Override - public void onPackageProcessKilledForUninstall(String packageName) { - mHandler.post(() -> PackageManagerService.this.notifyInstallObserver(packageName, - true /* killApp */)); - } - - @Override - public SparseArray<String> getAppsWithSharedUserIds() { - return mComputer.getAppsWithSharedUserIds(); - } - - @Override - @NonNull - public String[] getSharedUserPackagesForPackage(String packageName, int userId) { - return mComputer.getSharedUserPackagesForPackage(packageName, userId); - } - - @Override - public ArrayMap<String, ProcessInfo> getProcessesForUid(int uid) { - return mComputer.getProcessesForUid(uid); - } - - @Override - public int[] getPermissionGids(String permissionName, int userId) { - return mPermissionManager.getPermissionGids(permissionName, userId); - } - - @Override - public boolean isOnlyCoreApps() { - return mIPackageManager.isOnlyCoreApps(); - } - - @Override - public void freeStorage(String volumeUuid, long bytes, - @StorageManager.AllocateFlags int flags) throws IOException { - PackageManagerService.this.freeStorage(volumeUuid, bytes, flags); - } - - @Override - public void freeAllAppCacheAboveQuota(@NonNull String volumeUuid) throws IOException { - PackageManagerService.this.freeAllAppCacheAboveQuota(volumeUuid); - } - - @Override - public void forEachPackageSetting(Consumer<PackageSetting> actionLocked) { - PackageManagerService.this.forEachPackageSetting(actionLocked); - } - - @Override - public void forEachPackageState(Consumer<PackageStateInternal> action) { - PackageManagerService.this.forEachPackageState(action); - } - - @Override - public void forEachPackage(Consumer<AndroidPackage> action) { - PackageManagerService.this.forEachPackage(action); - } - - @Override - public void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> action, - @UserIdInt int userId) { - PackageManagerService.this.forEachInstalledPackage(action, userId); - } - - @Override - public ArraySet<String> getEnabledComponents(String packageName, int userId) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState == null) { - return new ArraySet<>(); - } - return packageState.getUserStateOrDefault(userId).getEnabledComponents(); - } - - @Override - public ArraySet<String> getDisabledComponents(String packageName, int userId) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState == null) { - return new ArraySet<>(); - } - return packageState.getUserStateOrDefault(userId).getDisabledComponents(); - } - - @Override - public @PackageManager.EnabledState int getApplicationEnabledState( - String packageName, int userId) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState == null) { - return COMPONENT_ENABLED_STATE_DEFAULT; - } - return packageState.getUserStateOrDefault(userId).getEnabledState(); - } - - @Override - public @PackageManager.EnabledState int getComponentEnabledSetting( - @NonNull ComponentName componentName, int callingUid, int userId) { - return PackageManagerService.this.mComputer.getComponentEnabledSettingInternal( - componentName, callingUid, userId); - } - - @Override - public void setEnableRollbackCode(int token, int enableRollbackCode) { - PackageManagerService.this.setEnableRollbackCode(token, enableRollbackCode); - } - /** * Ask the package manager to compile layouts in the given package. */ @@ -7869,11 +6322,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mArtManagerService.compileLayouts(pkg); } - @Override - public void finishPackageInstall(int token, boolean didLaunch) { - mIPackageManager.finishPackageInstall(token, didLaunch); - } - @Nullable @Override public String removeLegacyDefaultBrowserPackageName(int userId) { @@ -7883,16 +6331,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean isApexPackage(String packageName) { - return PackageManagerService.this.mApexManager.isApexPackage(packageName); - } - - @Override - public List<String> getApksInApex(String apexPackageName) { - return PackageManagerService.this.mApexManager.getApksInApex(apexPackageName); - } - - @Override public void uninstallApex(String packageName, long versionCode, int userId, IntentSender intentSender, int flags) { final int callerUid = Binder.getCallingUid(); @@ -7967,11 +6405,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean isCallerInstallerOfRecord(@NonNull AndroidPackage pkg, int callingUid) { - return mComputer.isCallerInstallerOfRecord(pkg, callingUid); - } - - @Override public boolean isPermissionUpgradeNeeded(int userId) { return mSettings.isPermissionUpgradeNeeded(userId); } @@ -7985,13 +6418,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public List<String> getMimeGroup(String packageName, String mimeGroup) { - return PackageManagerService.this.getMimeGroupInternal(packageName, mimeGroup); - } - - @Override public void setVisibilityLogging(String packageName, boolean enable) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); + final PackageStateInternal packageState = + snapshot().getPackageStateInternal(packageName); if (packageState == null) { throw new IllegalStateException("No package found for " + packageName); } @@ -7999,12 +6428,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean isSystemPackage(@NonNull String packageName) { - return packageName.equals( - PackageManagerService.this.ensureSystemPackageName(packageName)); - } - - @Override public void clearBlockUninstallForUser(@UserIdInt int userId) { synchronized (mLock) { mSettings.clearBlockUninstallLPw(userId); @@ -8013,21 +6436,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void unsuspendForSuspendingPackage(final String packageName, int affectedUser) { - PackageManagerService.this.unsuspendForSuspendingPackage(snapshotComputer(), - packageName, affectedUser); - } - - @Override - public boolean isSuspendingAnyPackages(String suspendingPackage, int userId) { - return PackageManagerService.this.isSuspendingAnyPackages(suspendingPackage, userId); - } - - @Override public boolean registerInstalledLoadingProgressCallback(String packageName, PackageManagerInternal.InstalledLoadingProgressCallback callback, int userId) { - final PackageStateInternal ps = - getPackageStateInstalledFiltered(packageName, Binder.getCallingUid(), userId); + final Computer snapshot = snapshotComputer(); + final PackageStateInternal ps = filterPackageStateForInstalledAndFiltered(snapshot, + packageName, Binder.getCallingUid(), userId); if (ps == null) { return false; } @@ -8048,8 +6461,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public IncrementalStatesInfo getIncrementalStatesInfo( @NonNull String packageName, int filterCallingUid, int userId) { - final PackageStateInternal ps = - getPackageStateInstalledFiltered(packageName, filterCallingUid, userId); + final Computer snapshot = snapshotComputer(); + final PackageStateInternal ps = filterPackageStateForInstalledAndFiltered(snapshot, + packageName, filterCallingUid, userId); if (ps == null) { return null; } @@ -8057,74 +6471,23 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public void requestChecksums(@NonNull String packageName, boolean includeSplits, - @Checksum.TypeMask int optional, @Checksum.TypeMask int required, - @Nullable List trustedInstallers, - @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, - @NonNull Executor executor, @NonNull Handler handler) { - requestChecksumsInternal(packageName, includeSplits, optional, required, - trustedInstallers, onChecksumsReadyListener, userId, executor, handler); - } - - @Override - public boolean isPackageFrozen(@NonNull String packageName, - int callingUid, int userId) { - return PackageManagerService.this.getPackageStartability( - packageName, callingUid, userId) == PACKAGE_STARTABILITY_FROZEN; - } - - @Override - public long deleteOatArtifactsOfPackage(String packageName) { - return PackageManagerService.this.deleteOatArtifactsOfPackage(packageName); - } - - @Override - public void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags, - boolean migrateAppsData) { - PackageManagerService.this.mAppDataHelper.reconcileAppsData(userId, flags, - migrateAppsData); - } - - @Override - @NonNull - public ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId) { - return PackageManagerService.this.mComputer.getSharedUserPackages(sharedUserAppId); - } - - @Override - @Nullable - public SharedUserApi getSharedUserApi(int sharedUserAppId) { - return mComputer.getSharedUser(sharedUserAppId); - } - - @NonNull - @Override - public PackageStateMutator.InitialState recordInitialState() { - return PackageManagerService.this.recordInitialState(); - } - - @Nullable - @Override - public PackageStateMutator.Result commitPackageStateMutation( - @Nullable PackageStateMutator.InitialState state, - @NonNull Consumer<PackageStateMutator> consumer) { - return PackageManagerService.this.commitPackageStateMutation(state, consumer); - } - - @NonNull - @Override - public Computer snapshot() { - return snapshotComputer(); - } + public boolean isSameApp(@Nullable String packageName, int callingUid, int userId) { + if (packageName == null) { + return false; + } - @Override - public void shutdown() { - PackageManagerService.this.shutdown(); + if (Process.isSdkSandboxUid(callingUid)) { + return packageName.equals(mRequiredSdkSandboxPackage); + } + Computer snapshot = snapshot(); + int uid = snapshot.getPackageUid(packageName, 0, userId); + return UserHandle.isSameApp(uid, callingUid); } @Override - public DynamicCodeLogger getDynamicCodeLogger() { - return PackageManagerService.this.getDexManager().getDynamicCodeLogger(); + public void onPackageProcessKilledForUninstall(String packageName) { + mHandler.post(() -> PackageManagerService.this.notifyInstallObserver(packageName, + true /* killApp */)); } } @@ -8239,24 +6602,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mSettings.getDisabledSystemPkgLPr(packageName); } - @VisibleForTesting(visibility = Visibility.PRIVATE) - @Nullable - PackageStateInternal getPackageStateInternal(String packageName) { - return mComputer.getPackageStateInternal(packageName); - } - - @Nullable - PackageStateInternal getPackageStateInternal(String packageName, int callingUid) { - return mComputer.getPackageStateInternal(packageName, callingUid); - } - - @Nullable - PackageStateInternal getPackageStateInstalledFiltered(@NonNull String packageName, - int callingUid, @UserIdInt int userId) { - return filterPackageStateForInstalledAndFiltered(mComputer, packageName, callingUid, - userId); - } - @Nullable private PackageStateInternal filterPackageStateForInstalledAndFiltered( @NonNull Computer computer, @NonNull String packageName, int callingUid, @@ -8272,22 +6617,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - @Nullable - private PackageState getPackageState(String packageName) { - return mComputer.getPackageStateCopied(packageName); - } - - @NonNull - ArrayMap<String, ? extends PackageStateInternal> getPackageStates() { - Computer computer = snapshotComputer(); - if (computer == mLiveComputer) { - return new ArrayMap<>(computer.getPackageStates()); - } else { - return computer.getPackageStates(); - } - } - - private void forEachPackageSetting(Consumer<PackageSetting> actionLocked) { + @Deprecated + void forEachPackageSetting(Consumer<PackageSetting> actionLocked) { synchronized (mLock) { int size = mSettings.getPackagesLocked().size(); for (int index = 0; index < size; index++) { @@ -8296,13 +6627,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - void forEachPackageState(Consumer<PackageStateInternal> consumer) { - forEachPackageState(mComputer.getPackageStates(), consumer); + void forEachPackageState(@NonNull Computer snapshot, Consumer<PackageStateInternal> consumer) { + forEachPackageState(snapshot.getPackageStates(), consumer); } - void forEachPackage(Consumer<AndroidPackage> consumer) { + void forEachPackage(@NonNull Computer snapshot, Consumer<AndroidPackage> consumer) { final ArrayMap<String, ? extends PackageStateInternal> packageStates = - mComputer.getPackageStates(); + snapshot.getPackageStates(); int size = packageStates.size(); for (int index = 0; index < size; index++) { PackageStateInternal packageState = packageStates.valueAt(index); @@ -8322,7 +6653,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> action, + void forEachInstalledPackage(@NonNull Computer snapshot, @NonNull Consumer<AndroidPackage> action, @UserIdInt int userId) { Consumer<PackageStateInternal> actionWrapped = packageState -> { if (packageState.getPkg() != null @@ -8330,7 +6661,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService action.accept(packageState.getPkg()); } }; - forEachPackageState(mComputer.getPackageStates(), actionWrapped); + forEachPackageState(snapshot.getPackageStates(), actionWrapped); } boolean isHistoricalPackageUsageAvailable() { @@ -8345,15 +6676,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mCompilerStats.getOrCreatePackageStats(pkgName); } - /** - * Returns true if the system or user is explicitly preventing an otherwise valid installer to - * complete an install. This includes checks like unknown sources and user restrictions. - */ - public boolean isInstallDisabledForPackage(String packageName, int uid, int userId) { - return mComputer.isInstallDisabledForPackage(packageName, uid, userId); - } - - private void grantImplicitAccess(@NonNull Computer snapshot, @UserIdInt int userId, + void grantImplicitAccess(@NonNull Computer snapshot, @UserIdInt int userId, Intent intent, @AppIdInt int recipientAppId, int visibleUid, boolean direct, boolean retainOnUpdate) { final AndroidPackage visiblePackage = snapshot.getPackage(visibleUid); @@ -8384,8 +6707,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - boolean canHaveOatDir(String packageName) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); + boolean canHaveOatDir(@NonNull Computer snapshot, String packageName) { + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState == null || packageState.getPkg() == null) { return false; } @@ -8393,8 +6716,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService packageState.getTransientState().isUpdatedSystemApp()); } - long deleteOatArtifactsOfPackage(String packageName) { - PackageStateInternal packageState = getPackageStateInternal(packageName); + long deleteOatArtifactsOfPackage(@NonNull Computer snapshot, String packageName) { + PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState == null || packageState.getPkg() == null) { return -1; // error code of deleteOptimizedFiles } @@ -8402,13 +6725,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService ArtUtils.createArtPackageInfo(packageState.getPkg(), packageState)); } - @NonNull - Set<String> getUnusedPackages(long downgradeTimeThresholdMillis) { - return mComputer.getUnusedPackages(downgradeTimeThresholdMillis); - } - - private List<String> getMimeGroupInternal(String packageName, String mimeGroup) { - final PackageStateInternal packageState = getPackageStateInternal(packageName); + List<String> getMimeGroupInternal(@NonNull Computer snapshot, String packageName, + String mimeGroup) { + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState == null) { return Collections.emptyList(); } @@ -8473,16 +6792,16 @@ public class PackageManagerService implements PackageSender, TestUtilityService * Returns the array containing per-uid timeout configuration. * This is derived from DeviceConfig flags. */ - public @NonNull PerUidReadTimeouts[] getPerUidReadTimeouts() { + public @NonNull PerUidReadTimeouts[] getPerUidReadTimeouts(@NonNull Computer snapshot) { PerUidReadTimeouts[] result = mPerUidReadTimeoutsCache; if (result == null) { - result = parsePerUidReadTimeouts(); + result = parsePerUidReadTimeouts(snapshot); mPerUidReadTimeoutsCache = result; } return result; } - private @NonNull PerUidReadTimeouts[] parsePerUidReadTimeouts() { + private @NonNull PerUidReadTimeouts[] parsePerUidReadTimeouts(@NonNull Computer snapshot) { final String defaultTimeouts = getDefaultTimeouts(); final String knownDigestersList = getKnownDigestersList(); final List<PerPackageReadTimeouts> perPackageReadTimeouts = @@ -8496,7 +6815,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService final List<PerUidReadTimeouts> result = new ArrayList<>(perPackageReadTimeouts.size()); for (int i = 0, size = perPackageReadTimeouts.size(); i < size; ++i) { final PerPackageReadTimeouts perPackage = perPackageReadTimeouts.get(i); - final PackageStateInternal ps = getPackageStateInternal(perPackage.packageName); + final PackageStateInternal ps = + snapshot.getPackageStateInternal(perPackage.packageName); if (ps == null) { if (DEBUG_PER_UID_READ_TIMEOUTS) { Slog.i(TAG, "PerUidReadTimeouts: package not found = " @@ -8546,7 +6866,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService return result.toArray(new PerUidReadTimeouts[result.size()]); } - private void setKeepUninstalledPackagesInternal(List<String> packageList) { + void setKeepUninstalledPackagesInternal(@NonNull Computer snapshot, List<String> packageList) { Preconditions.checkNotNull(packageList); synchronized (mKeepUninstalledPackages) { List<String> toRemove = new ArrayList<>(mKeepUninstalledPackages); @@ -8556,7 +6876,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mKeepUninstalledPackages.addAll(packageList); for (int i = 0; i < toRemove.size(); i++) { - deletePackageIfUnused(toRemove.get(i)); + deletePackageIfUnused(snapshot, toRemove.get(i)); } } } @@ -8603,43 +6923,44 @@ public class PackageManagerService implements PackageSender, TestUtilityService mInstrumentation.put(name, instrumentation); } - String[] getKnownPackageNamesInternal(int knownPackage, int userId) { + String[] getKnownPackageNamesInternal(@NonNull Computer snapshot, int knownPackage, + int userId) { switch (knownPackage) { case PackageManagerInternal.PACKAGE_BROWSER: return new String[] { mDefaultAppProvider.getDefaultBrowser(userId) }; case PackageManagerInternal.PACKAGE_INSTALLER: - return mComputer.filterOnlySystemPackages(mRequiredInstallerPackage); + return snapshot.filterOnlySystemPackages(mRequiredInstallerPackage); case PackageManagerInternal.PACKAGE_UNINSTALLER: - return mComputer.filterOnlySystemPackages(mRequiredUninstallerPackage); + return snapshot.filterOnlySystemPackages(mRequiredUninstallerPackage); case PackageManagerInternal.PACKAGE_SETUP_WIZARD: - return mComputer.filterOnlySystemPackages(mSetupWizardPackage); + return snapshot.filterOnlySystemPackages(mSetupWizardPackage); case PackageManagerInternal.PACKAGE_SYSTEM: return new String[]{"android"}; case PackageManagerInternal.PACKAGE_VERIFIER: - return mComputer.filterOnlySystemPackages(mRequiredVerifierPackage); + return snapshot.filterOnlySystemPackages(mRequiredVerifierPackage); case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER: - return mComputer.filterOnlySystemPackages( + return snapshot.filterOnlySystemPackages( mDefaultTextClassifierPackage, mSystemTextClassifierPackageName); case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER: - return mComputer.filterOnlySystemPackages(mRequiredPermissionControllerPackage); + return snapshot.filterOnlySystemPackages(mRequiredPermissionControllerPackage); case PackageManagerInternal.PACKAGE_CONFIGURATOR: - return mComputer.filterOnlySystemPackages(mConfiguratorPackage); + return snapshot.filterOnlySystemPackages(mConfiguratorPackage); case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER: - return mComputer.filterOnlySystemPackages(mIncidentReportApproverPackage); + return snapshot.filterOnlySystemPackages(mIncidentReportApproverPackage); case PackageManagerInternal.PACKAGE_AMBIENT_CONTEXT_DETECTION: - return mComputer.filterOnlySystemPackages(mAmbientContextDetectionPackage); + return snapshot.filterOnlySystemPackages(mAmbientContextDetectionPackage); case PackageManagerInternal.PACKAGE_APP_PREDICTOR: - return mComputer.filterOnlySystemPackages(mAppPredictionServicePackage); + return snapshot.filterOnlySystemPackages(mAppPredictionServicePackage); case PackageManagerInternal.PACKAGE_COMPANION: - return mComputer.filterOnlySystemPackages(COMPANION_PACKAGE_NAME); + return snapshot.filterOnlySystemPackages(COMPANION_PACKAGE_NAME); case PackageManagerInternal.PACKAGE_RETAIL_DEMO: return TextUtils.isEmpty(mRetailDemoPackage) ? ArrayUtils.emptyArray(String.class) : new String[] {mRetailDemoPackage}; case PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE: - return mComputer.filterOnlySystemPackages(getOverlayConfigSignaturePackageName()); + return snapshot.filterOnlySystemPackages(mOverlayConfigSignaturePackage); case PackageManagerInternal.PACKAGE_RECENTS: - return mComputer.filterOnlySystemPackages(mRecentsPackage); + return snapshot.filterOnlySystemPackages(mRecentsPackage); default: return ArrayUtils.emptyArray(String.class); } @@ -8659,10 +6980,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDefaultAppProvider.setDefaultBrowser(packageName, async, userId); } - ResolveInfo getInstantAppInstallerInfo() { - return mInstantAppInstallerInfo; - } - PackageUsage getPackageUsage() { return mPackageUsage; } @@ -8754,10 +7071,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - ResolveInfo getResolveInfo() { - return mResolveInfo; - } - ApplicationInfo getCoreAndroidApplication() { return mAndroidApplication; } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 8d3fbf7fc679..2a1a99068d45 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -850,6 +850,8 @@ public class PackageManagerServiceUtils { ret.recommendedInstallLocation = recommendedInstallLocation; ret.multiArch = pkg.isMultiArch(); ret.debuggable = pkg.isDebuggable(); + ret.isSdkLibrary = pkg.isIsSdkLibrary(); + return ret; } diff --git a/services/core/java/com/android/server/pm/PackageSender.java b/services/core/java/com/android/server/pm/PackageSender.java index d380098d44b3..656d5962e1a9 100644 --- a/services/core/java/com/android/server/pm/PackageSender.java +++ b/services/core/java/com/android/server/pm/PackageSender.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.IIntentReceiver; import android.os.Bundle; @@ -30,9 +31,9 @@ interface PackageSender { Bundle extras, int flags, String targetPkg, IIntentReceiver finishedReceiver, int[] userIds, int[] instantUserIds, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable Bundle bOptions); - void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted, - boolean includeStopped, int appId, int[] userIds, int[] instantUserIds, - int dataLoaderType); + void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName, + boolean sendBootCompleted, boolean includeStopped, int appId, int[] userIds, + int[] instantUserIds, 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 7253ae4e7cb0..9befd6e09eb4 100644 --- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java +++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java @@ -25,6 +25,7 @@ import static com.android.server.pm.PackageManagerService.DEBUG_PREFERRED; import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; @@ -74,17 +75,18 @@ final class PreferredActivityHelper { mPm = pm; } - private ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, - @PackageManager.ResolveInfoFlagsBits long flags, List<ResolveInfo> query, - boolean always, boolean removeMatches, boolean debug, int userId) { - return findPreferredActivityNotLocked( - intent, resolvedType, flags, query, always, removeMatches, debug, userId, + private ResolveInfo findPreferredActivityNotLocked(@NonNull Computer snapshot, Intent intent, + String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, + List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug, + @UserIdInt int userId) { + return findPreferredActivityNotLocked(snapshot, intent, resolvedType, flags, query, always, + removeMatches, debug, userId, UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID); } // TODO: handle preferred activities missing while user has amnesia /** <b>must not hold {@link PackageManagerService.mLock}</b> */ - public ResolveInfo findPreferredActivityNotLocked( + public ResolveInfo findPreferredActivityNotLocked(@NonNull Computer snapshot, Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) { @@ -95,7 +97,7 @@ final class PreferredActivityHelper { if (!mPm.mUserManager.exists(userId)) return null; PackageManagerService.FindPreferredActivityBodyResult body = - mPm.findPreferredActivityInternal( + snapshot.findPreferredActivityInternal( intent, resolvedType, flags, query, always, removeMatches, debug, userId, queryMayBeFiltered); if (body.mChanged) { @@ -117,7 +119,7 @@ final class PreferredActivityHelper { mPm.clearPackagePreferredActivitiesLPw(packageName, changedUsers, userId); } if (changedUsers.size() > 0) { - updateDefaultHomeNotLocked(changedUsers); + updateDefaultHomeNotLocked(mPm.snapshotComputer(), changedUsers); mPm.postPreferredActivityChangedBroadcast(userId); mPm.scheduleWritePackageRestrictions(userId); } @@ -128,7 +130,7 @@ final class PreferredActivityHelper { * * @return Whether the ACTION_PREFERRED_ACTIVITY_CHANGED broadcast has been scheduled. */ - public boolean updateDefaultHomeNotLocked(int userId) { + public boolean updateDefaultHomeNotLocked(@NonNull Computer snapshot, @UserIdInt int userId) { if (Thread.holdsLock(mPm.mLock)) { Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mLock", new Throwable()); @@ -139,10 +141,10 @@ final class PreferredActivityHelper { // before that. return false; } - final Intent intent = mPm.getHomeIntent(); - final List<ResolveInfo> resolveInfos = mPm.snapshotComputer().queryIntentActivitiesInternal( + final Intent intent = snapshot.getHomeIntent(); + final List<ResolveInfo> resolveInfos = snapshot.queryIntentActivitiesInternal( intent, null, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId); - final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked( + final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked(snapshot, intent, null, 0, resolveInfos, true, false, false, userId); final String packageName = preferredResolveInfo != null && preferredResolveInfo.activityInfo != null @@ -151,8 +153,7 @@ final class PreferredActivityHelper { if (TextUtils.equals(currentPackageName, packageName)) { return false; } - final String[] callingPackages = mPm.mIPackageManager - .getPackagesForUid(Binder.getCallingUid()); + final String[] callingPackages = snapshot.getPackagesForUid(Binder.getCallingUid()); if (callingPackages != null && ArrayUtils.contains(callingPackages, mPm.mRequiredPermissionControllerPackage)) { // PermissionController manages default home directly. @@ -174,23 +175,21 @@ final class PreferredActivityHelper { /** * Variant that takes a {@link WatchedIntentFilter} */ - public void addPreferredActivity(WatchedIntentFilter filter, int match, - ComponentName[] set, ComponentName activity, boolean always, int userId, + public void addPreferredActivity(@NonNull Computer snapshot, WatchedIntentFilter filter, + int match, ComponentName[] set, ComponentName activity, boolean always, int userId, String opname, boolean removeExisting) { // writer int callingUid = Binder.getCallingUid(); - mPm.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, + snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "add preferred activity"); if (mPm.mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - synchronized (mPm.mLock) { - if (mPm.getUidTargetSdkVersion(callingUid) - < Build.VERSION_CODES.FROYO) { - Slog.w(TAG, "Ignoring addPreferredActivity() from uid " - + callingUid); - return; - } + if (snapshot.getUidTargetSdkVersion(callingUid) + < Build.VERSION_CODES.FROYO) { + Slog.w(TAG, "Ignoring addPreferredActivity() from uid " + + callingUid); + return; } mPm.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); @@ -214,7 +213,8 @@ final class PreferredActivityHelper { new PreferredActivity(filter, match, set, activity, always)); mPm.scheduleWritePackageRestrictions(userId); } - if (!(isHomeFilter(filter) && updateDefaultHomeNotLocked(userId))) { + // Re-snapshot after mLock + if (!(isHomeFilter(filter) && updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId))) { mPm.postPreferredActivityChangedBroadcast(userId); } } @@ -222,8 +222,8 @@ final class PreferredActivityHelper { /** * Variant that takes a {@link WatchedIntentFilter} */ - public void replacePreferredActivity(WatchedIntentFilter filter, int match, - ComponentName[] set, ComponentName activity, int userId) { + public void replacePreferredActivity(@NonNull Computer snapshot, WatchedIntentFilter filter, + int match, ComponentName[] set, ComponentName activity, int userId) { if (filter.countActions() != 1) { throw new IllegalArgumentException( "replacePreferredActivity expects filter to have only 1 action."); @@ -238,13 +238,14 @@ final class PreferredActivityHelper { } final int callingUid = Binder.getCallingUid(); - mPm.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, + snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "replace preferred activity"); if (mPm.mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { synchronized (mPm.mLock) { - if (mPm.getUidTargetSdkVersion(callingUid) + // TODO: Remove lock? + if (mPm.snapshotComputer().getUidTargetSdkVersion(callingUid) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring replacePreferredActivity() from uid " + Binder.getCallingUid()); @@ -296,21 +297,23 @@ final class PreferredActivityHelper { } } } - addPreferredActivity(filter, match, set, activity, true, userId, + + // Retake a snapshot after editing with lock held + addPreferredActivity(mPm.snapshotComputer(), filter, match, set, activity, true, userId, "Replacing preferred", false); } - public void clearPackagePreferredActivities(String packageName) { + public void clearPackagePreferredActivities(@NonNull Computer snapshot, String packageName) { final int callingUid = Binder.getCallingUid(); - if (mPm.getInstantAppPackageName(callingUid) != null) { + if (snapshot.getInstantAppPackageName(callingUid) != null) { return; } - final PackageStateInternal packageState = mPm.getPackageStateInternal(packageName); - if (packageState == null || !mPm.isCallerSameApp(packageName, callingUid)) { + final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); + if (packageState == null || !snapshot.isCallerSameApp(packageName, callingUid)) { if (mPm.mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - if (mPm.getUidTargetSdkVersion(callingUid) + if (snapshot.getUidTargetSdkVersion(callingUid) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid " + callingUid); @@ -320,7 +323,7 @@ final class PreferredActivityHelper { android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); } } - if (packageState != null && mPm.shouldFilterApplication(packageState, callingUid, + if (packageState != null && snapshot.shouldFilterApplication(packageState, callingUid, UserHandle.getUserId(callingUid))) { return; } @@ -329,23 +332,23 @@ final class PreferredActivityHelper { } /** <b>must not hold {@link #PackageManagerService.mLock}</b> */ - void updateDefaultHomeNotLocked(SparseBooleanArray userIds) { + void updateDefaultHomeNotLocked(@NonNull Computer snapshot, SparseBooleanArray userIds) { if (Thread.holdsLock(mPm.mLock)) { Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mLock", new Throwable()); } for (int i = userIds.size() - 1; i >= 0; --i) { final int userId = userIds.keyAt(i); - updateDefaultHomeNotLocked(userId); + updateDefaultHomeNotLocked(snapshot, userId); } } - public void setHomeActivity(ComponentName comp, int userId) { - if (mPm.getInstantAppPackageName(Binder.getCallingUid()) != null) { + public void setHomeActivity(@NonNull Computer snapshot, ComponentName comp, int userId) { + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { return; } ArrayList<ResolveInfo> homeActivities = new ArrayList<>(); - mPm.getHomeActivitiesAsUser(homeActivities, userId); + snapshot.getHomeActivitiesAsUser(homeActivities, userId); boolean found = false; @@ -364,7 +367,7 @@ final class PreferredActivityHelper { throw new IllegalArgumentException("Component " + comp + " cannot be home on user " + userId); } - replacePreferredActivity(getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY, + replacePreferredActivity(snapshot, getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY, set, comp, userId); } @@ -401,7 +404,7 @@ final class PreferredActivityHelper { mPm.scheduleWritePackageRestrictions(userId); } if (isHomeFilter(filter)) { - updateDefaultHomeNotLocked(userId); + updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId); } mPm.postPreferredActivityChangedBroadcast(userId); } @@ -417,7 +420,7 @@ final class PreferredActivityHelper { changed = mPm.mSettings.clearPackagePersistentPreferredActivities(packageName, userId); } if (changed) { - updateDefaultHomeNotLocked(userId); + updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId); mPm.postPreferredActivityChangedBroadcast(userId); mPm.scheduleWritePackageRestrictions(userId); } @@ -506,7 +509,7 @@ final class PreferredActivityHelper { synchronized (mPm.mLock) { mPm.mSettings.readPreferredActivitiesLPw(readParser, readUserId); } - updateDefaultHomeNotLocked(readUserId); + updateDefaultHomeNotLocked(mPm.snapshotComputer(), readUserId); }); } catch (Exception e) { if (DEBUG_BACKUP) { @@ -598,7 +601,7 @@ final class PreferredActivityHelper { mPm.mPermissionManager.resetRuntimePermissions(pkg, userId); } } - updateDefaultHomeNotLocked(userId); + updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId); resetNetworkPolicies(userId); mPm.scheduleWritePackageRestrictions(userId); } finally { @@ -610,12 +613,11 @@ final class PreferredActivityHelper { mPm.mInjector.getLocalService(NetworkPolicyManagerInternal.class).resetUserState(userId); } - // TODO: This method should not touch the Computer directly - public int getPreferredActivities(List<IntentFilter> outFilters, - List<ComponentName> outActivities, String packageName, Computer computer) { + public int getPreferredActivities(@NonNull Computer snapshot, List<IntentFilter> outFilters, + List<ComponentName> outActivities, String packageName) { List<WatchedIntentFilter> temp = WatchedIntentFilter.toWatchedIntentFilterList(outFilters); - int result = getPreferredActivitiesInternal(temp, outActivities, packageName, computer); + int result = getPreferredActivitiesInternal(snapshot, temp, outActivities, packageName); outFilters.clear(); for (int i = 0; i < temp.size(); i++) { outFilters.add(temp.get(i).getIntentFilter()); @@ -626,16 +628,17 @@ final class PreferredActivityHelper { /** * Variant that takes a {@link WatchedIntentFilter} */ - private int getPreferredActivitiesInternal(List<WatchedIntentFilter> outFilters, - List<ComponentName> outActivities, String packageName, Computer computer) { + private int getPreferredActivitiesInternal(@NonNull Computer snapshot, + List<WatchedIntentFilter> outFilters, List<ComponentName> outActivities, + String packageName) { final int callingUid = Binder.getCallingUid(); - if (mPm.getInstantAppPackageName(callingUid) != null) { + if (snapshot.getInstantAppPackageName(callingUid) != null) { return 0; } int num = 0; final int userId = UserHandle.getCallingUserId(); - PreferredIntentResolver pir = computer.getPreferredActivities(userId); + PreferredIntentResolver pir = snapshot.getPreferredActivities(userId); if (pir != null) { final Iterator<PreferredActivity> it = pir.filterIterator(); while (it.hasNext()) { @@ -643,8 +646,9 @@ final class PreferredActivityHelper { final String prefPackageName = pa.mPref.mComponent.getPackageName(); if (packageName == null || (prefPackageName.equals(packageName) && pa.mPref.mAlways)) { - if (mPm.shouldFilterApplication( - mPm.getPackageStateInternal(prefPackageName), callingUid, userId)) { + if (snapshot.shouldFilterApplication( + snapshot.getPackageStateInternal(prefPackageName), callingUid, + userId)) { continue; } if (outFilters != null) { @@ -660,7 +664,8 @@ final class PreferredActivityHelper { return num; } - public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) { + public ResolveInfo findPersistentPreferredActivity(@NonNull Computer snapshot, Intent intent, + int userId) { if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.SYSTEM_UID)) { throw new SecurityException( "findPersistentPreferredActivity can only be run by the system"); @@ -671,24 +676,23 @@ final class PreferredActivityHelper { final int callingUid = Binder.getCallingUid(); intent = PackageManagerServiceUtils.updateIntentForResolve(intent); final String resolvedType = intent.resolveTypeIfNeeded(mPm.mContext.getContentResolver()); - final long flags = mPm.updateFlagsForResolve( + final long flags = snapshot.updateFlagsForResolve( 0, userId, callingUid, false /*includeInstantApps*/, - mPm.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType, + snapshot.isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType, 0)); - final List<ResolveInfo> query = mPm.snapshotComputer().queryIntentActivitiesInternal(intent, + final List<ResolveInfo> query = snapshot.queryIntentActivitiesInternal(intent, resolvedType, flags, userId); - synchronized (mPm.mLock) { - return mPm.findPersistentPreferredActivityLP(intent, resolvedType, flags, query, false, - userId); - } + return snapshot.findPersistentPreferredActivity(intent, resolvedType, flags, query, false, + userId); } /** * Variant that takes a {@link WatchedIntentFilter} */ - public void setLastChosenActivity(Intent intent, String resolvedType, int flags, - WatchedIntentFilter filter, int match, ComponentName activity) { - if (mPm.getInstantAppPackageName(Binder.getCallingUid()) != null) { + public void setLastChosenActivity(@NonNull Computer snapshot, Intent intent, + String resolvedType, int flags, WatchedIntentFilter filter, int match, + ComponentName activity) { + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { return; } final int userId = UserHandle.getCallingUserId(); @@ -702,25 +706,26 @@ final class PreferredActivityHelper { filter.dump(new PrintStreamPrinter(System.out), " "); } intent.setComponent(null); - final List<ResolveInfo> query = mPm.snapshotComputer().queryIntentActivitiesInternal(intent, + final List<ResolveInfo> query = snapshot.queryIntentActivitiesInternal(intent, resolvedType, flags, userId); // Find any earlier preferred or last chosen entries and nuke them - findPreferredActivityNotLocked( - intent, resolvedType, flags, query, false, true, false, userId); + findPreferredActivityNotLocked(snapshot, intent, resolvedType, flags, query, false, true, + false, userId); // Add the new activity as the last chosen for this filter - addPreferredActivity(filter, match, null, activity, false, userId, + addPreferredActivity(snapshot, filter, match, null, activity, false, userId, "Setting last chosen", false); } - public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) { - if (mPm.getInstantAppPackageName(Binder.getCallingUid()) != null) { + public ResolveInfo getLastChosenActivity(@NonNull Computer snapshot, Intent intent, + String resolvedType, int flags) { + if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) { return null; } final int userId = UserHandle.getCallingUserId(); if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent); - final List<ResolveInfo> query = mPm.snapshotComputer().queryIntentActivitiesInternal(intent, + final List<ResolveInfo> query = snapshot.queryIntentActivitiesInternal(intent, resolvedType, flags, userId); - return findPreferredActivityNotLocked( - intent, resolvedType, flags, query, false, false, false, userId); + return findPreferredActivityNotLocked(snapshot, intent, resolvedType, flags, query, false, + false, false, userId); } } diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java index 4ec042f79052..2a1ca2c41e64 100644 --- a/services/core/java/com/android/server/pm/PreferredComponent.java +++ b/services/core/java/com/android/server/pm/PreferredComponent.java @@ -57,7 +57,6 @@ public class PreferredComponent { private String mParseError; private final Callbacks mCallbacks; - private final String mSetupWizardPackageName; public interface Callbacks { public boolean onReadTag(String tagName, TypedXmlPullParser parser) @@ -72,7 +71,6 @@ public class PreferredComponent { mAlways = always; mShortComponent = component.flattenToShortString(); mParseError = null; - mSetupWizardPackageName = null; if (set != null) { final int N = set.length; String[] myPackages = new String[N]; @@ -174,8 +172,6 @@ public class PreferredComponent { mSetPackages = myPackages; mSetClasses = myClasses; mSetComponents = myComponents; - final PackageManagerInternal packageManagerInternal = LocalServices.getService(PackageManagerInternal.class); - mSetupWizardPackageName = packageManagerInternal.getSetupWizardPackageName(); } public String getParseError() { @@ -209,6 +205,7 @@ public class PreferredComponent { final int NQ = query.size(); final int NS = mSetPackages.length; final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); + String setupWizardPackageName = pmi.getSetupWizardPackageName(); int numMatch = 0; for (int i=0; i<NQ; i++) { ResolveInfo ri = query.get(i); @@ -217,7 +214,7 @@ public class PreferredComponent { // ignore SetupWizard package's launcher capability because it is only existed // during SetupWizard is running - if (excludeSetupWizardPackage && ai.packageName.equals(mSetupWizardPackageName)) { + if (excludeSetupWizardPackage && ai.packageName.equals(setupWizardPackageName)) { continue; } @@ -307,6 +304,8 @@ public class PreferredComponent { if (!excludeSetupWizardPackage && NS < NQ) { return false; } + final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); + String setupWizardPackageName = pmi.getSetupWizardPackageName(); for (int i=0; i<NQ; i++) { ResolveInfo ri = query.get(i); ActivityInfo ai = ri.activityInfo; @@ -314,7 +313,7 @@ public class PreferredComponent { // ignore SetupWizard package's launcher capability because it is only existed // during SetupWizard is running - if (excludeSetupWizardPackage && ai.packageName.equals(mSetupWizardPackageName)) { + if (excludeSetupWizardPackage && ai.packageName.equals(setupWizardPackageName)) { continue; } diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java index 88df843ec8c5..b181cdd92379 100644 --- a/services/core/java/com/android/server/pm/RemovePackageHelper.java +++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java @@ -118,7 +118,8 @@ final class RemovePackageHelper { public void removePackageLI(AndroidPackage pkg, boolean chatty) { // Remove the parent package setting - PackageStateInternal ps = mPm.getPackageStateInternal(pkg.getPackageName()); + PackageStateInternal ps = mPm.snapshotComputer() + .getPackageStateInternal(pkg.getPackageName()); if (ps != null) { removePackageLI(ps.getPackageName(), chatty); } else if (DEBUG_REMOVE && chatty) { @@ -271,8 +272,8 @@ final class RemovePackageHelper { synchronized (mPm.mLock) { mPm.mDomainVerificationManager.clearPackage(deletedPs.getPackageName()); mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName); - mPm.mAppsFilter.removePackage(mPm.getPackageStateInternal(packageName), - false /* isReplace */); + mPm.mAppsFilter.removePackage(mPm.snapshotComputer() + .getPackageStateInternal(packageName), false /* isReplace */); removedAppId = mPm.mSettings.removePackageLPw(packageName); if (outInfo != null) { outInfo.mRemovedAppId = removedAppId; @@ -298,7 +299,8 @@ final class RemovePackageHelper { if (changedUsers.size() > 0) { final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm); - preferredActivityHelper.updateDefaultHomeNotLocked(changedUsers); + preferredActivityHelper.updateDefaultHomeNotLocked(mPm.snapshotComputer(), + changedUsers); mPm.postPreferredActivityChangedBroadcast(UserHandle.USER_ALL); } } diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java index 25356a489217..b74670b77a11 100644 --- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java +++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java @@ -115,7 +115,7 @@ final class ResolveIntentHelper { if (!mUserManager.exists(userId)) return null; final int callingUid = Binder.getCallingUid(); flags = computer.updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart, - computer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, + computer.isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType, flags)); computer.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "resolve intent"); @@ -170,9 +170,9 @@ final class ResolveIntentHelper { } // If we have saved a preference for a preferred activity for // this Intent, use that. - ResolveInfo ri = mPreferredActivityHelper.findPreferredActivityNotLocked(intent, - resolvedType, flags, query, true, false, debug, userId, - queryMayBeFiltered); + ResolveInfo ri = mPreferredActivityHelper.findPreferredActivityNotLocked(computer, + intent, resolvedType, flags, query, true, false, debug, + userId, queryMayBeFiltered); if (ri != null) { return ri; } @@ -317,7 +317,7 @@ final class ResolveIntentHelper { final String instantAppPkgName = computer.getInstantAppPackageName(filterCallingUid); flags = computer.updateFlagsForResolve(flags, userId, filterCallingUid, false /*includeInstantApps*/, - computer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, + computer.isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType, flags)); Intent originalIntent = null; ComponentName comp = intent.getComponent(); @@ -562,7 +562,7 @@ final class ResolveIntentHelper { final int callingUid = Binder.getCallingUid(); flags = computer.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/, - computer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, + computer.isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType, flags)); computer.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "query intent activity options"); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 021c3db35756..6ccaae148ce6 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -40,7 +40,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; -import android.content.pm.ComponentInfo; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; @@ -113,11 +112,9 @@ import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; -import com.android.server.pm.pkg.PackageUserStateUtils; import com.android.server.pm.pkg.SuspendParams; import com.android.server.pm.pkg.component.ParsedComponent; import com.android.server.pm.pkg.component.ParsedIntentInfo; -import com.android.server.pm.pkg.component.ParsedMainComponent; import com.android.server.pm.pkg.component.ParsedPermission; import com.android.server.pm.pkg.component.ParsedProcess; import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; @@ -476,9 +473,9 @@ public final class Settings implements Watchable, Snappable { @Watched final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>(); @Watched - private final WatchedArrayList<SettingBase> mAppIds; + private final AppIdSettingMap mAppIds; @Watched - private final WatchedSparseArray<SettingBase> mOtherAppIds; + private final AppIdSettingMap mOtherAppIds; // For reading/writing settings file. @Watched @@ -594,8 +591,8 @@ public final class Settings implements Watchable, Snappable { mLock = new PackageManagerTracedLock(); mPackages.putAll(pkgSettings); - mAppIds = new WatchedArrayList<>(); - mOtherAppIds = new WatchedSparseArray<>(); + mAppIds = new AppIdSettingMap(); + mOtherAppIds = new AppIdSettingMap(); mSystemDir = null; mPermissions = null; mRuntimePermissionsPersistence = null; @@ -631,8 +628,8 @@ public final class Settings implements Watchable, Snappable { mKeySetManagerService = new KeySetManagerService(mPackages); mLock = lock; - mAppIds = new WatchedArrayList<>(); - mOtherAppIds = new WatchedSparseArray<>(); + mAppIds = new AppIdSettingMap(); + mOtherAppIds = new AppIdSettingMap(); mPermissions = new LegacyPermissionSettings(lock); mRuntimePermissionsPersistence = new RuntimePermissionPersistence( runtimePermissionsPersistence, new Consumer<Integer>() { @@ -1278,7 +1275,8 @@ public final class Settings implements Watchable, Snappable { // Utility method that adds a PackageSetting to mPackages and // completes updating the shared user attributes and any restored // app link verification state - private void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) + void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) { mPackages.put(p.getPackageName(), p); if (sharedUser != null) { SharedUserSetting existingSharedUserSetting = getSharedUserSettingLPr(p); @@ -1301,7 +1299,7 @@ public final class Settings implements Watchable, Snappable { p.setAppId(sharedUser.mAppId); } - // If the we know about this user id, we have to update it as it + // If we know about this user id, we have to update it as it // has to point to the same PackageSetting instance as the package. Object userIdPs = getSettingLPr(p.getAppId()); if (sharedUser == null) { @@ -1366,20 +1364,13 @@ public final class Settings implements Watchable, Snappable { } if (appId >= Process.FIRST_APPLICATION_UID) { - int size = mAppIds.size(); - final int index = appId - Process.FIRST_APPLICATION_UID; - // fill the array until our index becomes valid - while (index >= size) { - mAppIds.add(null); - size++; - } - if (mAppIds.get(index) != null) { + if (mAppIds.get(appId) != null) { PackageManagerService.reportSettingsProblem(Log.WARN, "Adding duplicate app id: " + appId + " name=" + name); return false; } - mAppIds.set(index, obj); + mAppIds.put(appId, obj); } else { if (mOtherAppIds.get(appId) != null) { PackageManagerService.reportSettingsProblem(Log.WARN, @@ -1395,9 +1386,7 @@ public final class Settings implements Watchable, Snappable { /** Gets the setting associated with the provided App ID */ public SettingBase getSettingLPr(int appId) { if (appId >= Process.FIRST_APPLICATION_UID) { - final int size = mAppIds.size(); - final int index = appId - Process.FIRST_APPLICATION_UID; - return index < size ? mAppIds.get(index) : null; + return mAppIds.get(appId); } else { return mOtherAppIds.get(appId); } @@ -1406,9 +1395,7 @@ public final class Settings implements Watchable, Snappable { /** Unregisters the provided app ID. */ void removeAppIdLPw(int appId) { if (appId >= Process.FIRST_APPLICATION_UID) { - final int size = mAppIds.size(); - final int index = appId - Process.FIRST_APPLICATION_UID; - if (index < size) mAppIds.set(index, null); + mAppIds.remove(appId); } else { mOtherAppIds.remove(appId); } @@ -1417,9 +1404,14 @@ public final class Settings implements Watchable, Snappable { private void replaceAppIdLPw(int appId, SettingBase obj) { if (appId >= Process.FIRST_APPLICATION_UID) { - final int size = mAppIds.size(); - final int index = appId - Process.FIRST_APPLICATION_UID; - if (index < size) mAppIds.set(index, obj); + if (appId <= mAppIds.getCurrentMaxAppId()) { + mAppIds.put(appId, obj); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: calling replaceAppIdLpw to" + + " replace SettingBase at appId=" + appId + + " but nothing is replaced."); + } } else { mOtherAppIds.put(appId, obj); } @@ -4304,22 +4296,21 @@ public final class Settings implements Watchable, Snappable { /** Returns a new AppID or -1 if we could not find an available AppID to assign */ private int acquireAndRegisterNewAppIdLPw(SettingBase obj) { - // Let's be stupidly inefficient for now... - final int size = mAppIds.size(); - for (int i = mFirstAvailableUid - Process.FIRST_APPLICATION_UID; i < size; i++) { - if (mAppIds.get(i) == null) { - mAppIds.set(i, obj); - return Process.FIRST_APPLICATION_UID + i; + final int nextAvailableAppId = mAppIds.getNextAvailableAppId(); + for (int uid = mFirstAvailableUid; uid < nextAvailableAppId; uid++) { + if (mAppIds.get(uid) == null) { + mAppIds.put(uid, obj); + return uid; } } // None left? - if (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) { + if (nextAvailableAppId > Process.LAST_APPLICATION_UID) { return -1; } - mAppIds.add(obj); - return Process.FIRST_APPLICATION_UID + size; + mAppIds.put(nextAvailableAppId, obj); + return nextAvailableAppId; } public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) { @@ -4354,33 +4345,6 @@ public final class Settings implements Watchable, Snappable { return getDisabledSystemPkgLPr(enabledPackageSetting.getPackageName()); } - boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, long flags, int userId) { - final PackageSetting ps = mPackages.get(componentInfo.packageName); - if (ps == null) return false; - - final PackageUserStateInternal userState = ps.readUserState(userId); - return PackageUserStateUtils.isMatch(userState, componentInfo, flags); - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedMainComponent component, - long flags, int userId) { - final PackageSetting ps = mPackages.get(component.getPackageName()); - if (ps == null) return false; - - final PackageUserStateInternal userState = ps.readUserState(userId); - return PackageUserStateUtils.isMatch(userState, pkg.isSystem(), pkg.isEnabled(), component, - flags); - } - - boolean isOrphaned(String packageName) { - final PackageSetting pkg = mPackages.get(packageName); - if (pkg == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - return pkg.getInstallSource().isOrphaned; - } - int getApplicationEnabledSettingLPr(String packageName, int userId) throws PackageManager.NameNotFoundException { final PackageSetting pkg = mPackages.get(packageName); diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java index 3fe079034cf2..479a404c88bf 100644 --- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java +++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java @@ -741,9 +741,11 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable } SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx); + final Computer snapshot = mPm.snapshotComputer(); + // Remove the shared library overlays from its dependent packages. for (int currentUserId : mPm.mUserManager.getUserIds()) { - final List<VersionedPackage> dependents = mPm.getPackagesUsingSharedLibrary( + final List<VersionedPackage> dependents = snapshot.getPackagesUsingSharedLibrary( libraryInfo, 0, Process.SYSTEM_UID, currentUserId); if (dependents == null) { continue; diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java index bb7e55a4bf40..df19d3e58bfd 100644 --- a/services/core/java/com/android/server/pm/StorageEventHelper.java +++ b/services/core/java/com/android/server/pm/StorageEventHelper.java @@ -26,13 +26,13 @@ import static com.android.server.pm.PackageManagerService.SCAN_INITIAL; import static com.android.server.pm.PackageManagerService.TAG; import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; +import android.annotation.NonNull; import android.app.ResourcesManager; import android.content.IIntentReceiver; import android.content.pm.PackageManager; import android.content.pm.PackagePartitions; import android.content.pm.UserInfo; import android.content.pm.VersionedPackage; -import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import android.os.Environment; import android.os.FileUtils; import android.os.UserHandle; @@ -48,6 +48,7 @@ import android.util.Slog; import com.android.internal.policy.AttributeCache; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import java.io.File; import java.util.ArrayList; @@ -78,7 +79,7 @@ public final class StorageEventHelper extends StorageEventListener { // Clean up any users or apps that were removed or recreated // while this volume was missing mPm.mUserManager.reconcileUsers(volumeUuid); - reconcileApps(volumeUuid); + reconcileApps(mPm.snapshotComputer(), volumeUuid); // Clean up any install sessions that expired or were // cancelled while this volume was missing @@ -299,8 +300,8 @@ public final class StorageEventHelper extends StorageEventListener { * aren't expected, either due to uninstallation or reinstallation on * another volume. */ - public void reconcileApps(String volumeUuid) { - List<String> absoluteCodePaths = collectAbsoluteCodePaths(); + public void reconcileApps(@NonNull Computer snapshot, String volumeUuid) { + List<String> absoluteCodePaths = collectAbsoluteCodePaths(snapshot); List<File> filesToDelete = null; final File[] files = FileUtils.listFilesOrEmpty( @@ -345,10 +346,10 @@ public final class StorageEventHelper extends StorageEventListener { } } - private List<String> collectAbsoluteCodePaths() { + private List<String> collectAbsoluteCodePaths(@NonNull Computer snapshot) { List<String> codePaths = new ArrayList<>(); final ArrayMap<String, ? extends PackageStateInternal> packageStates = - mPm.getPackageStates(); + snapshot.getPackageStates(); final int packageCount = packageStates.size(); for (int i = 0; i < packageCount; i++) { final PackageStateInternal ps = packageStates.valueAt(i); diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java index 3ef5599385ce..588dfaf6db78 100644 --- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java +++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java @@ -100,14 +100,14 @@ public final class SuspendPackageHelper { * @return The names of failed packages. */ @Nullable - String[] setPackagesSuspended(@NonNull Computer computer, @Nullable String[] packageNames, + String[] setPackagesSuspended(@NonNull Computer snapshot, @Nullable String[] packageNames, boolean suspended, @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras, @Nullable SuspendDialogInfo dialogInfo, @NonNull String callingPackage, @UserIdInt int userId, int callingUid) { if (ArrayUtils.isEmpty(packageNames)) { return packageNames; } - if (suspended && !isSuspendAllowedForUser(userId, callingUid)) { + if (suspended && !isSuspendAllowedForUser(snapshot, userId, callingUid)) { Slog.w(TAG, "Cannot suspend due to restrictions on user " + userId); return packageNames; } @@ -123,7 +123,7 @@ public final class SuspendPackageHelper { ArraySet<String> modifiedPackages = new ArraySet<>(); final boolean[] canSuspend = suspended - ? canSuspendPackageForUser(computer, packageNames, userId, callingUid) : null; + ? canSuspendPackageForUser(snapshot, packageNames, userId, callingUid) : null; for (int i = 0; i < packageNames.length; i++) { final String packageName = packageNames[i]; if (callingPackage.equals(packageName)) { @@ -133,9 +133,9 @@ public final class SuspendPackageHelper { continue; } final PackageStateInternal packageState = - computer.getPackageStateInternal(packageName); + snapshot.getPackageStateInternal(packageName); if (packageState == null - || computer.shouldFilterApplication(packageState, callingUid, userId)) { + || snapshot.shouldFilterApplication(packageState, callingUid, userId)) { Slog.w(TAG, "Could not find package setting for package: " + packageName + ". Skipping suspending/un-suspending."); unmodifiablePackages.add(packageName); @@ -191,9 +191,11 @@ public final class SuspendPackageHelper { } }); + final Computer newSnapshot = mPm.snapshotComputer(); + if (!changedPackagesList.isEmpty()) { final String[] changedPackages = changedPackagesList.toArray(new String[0]); - sendPackagesSuspendedForUser( + sendPackagesSuspendedForUser(newSnapshot, suspended ? Intent.ACTION_PACKAGES_SUSPENDED : Intent.ACTION_PACKAGES_UNSUSPENDED, changedPackages, changedUids.toArray(), userId); @@ -202,7 +204,7 @@ public final class SuspendPackageHelper { } // Send the suspension changed broadcast to ensure suspension state is not stale. if (!modifiedPackages.isEmpty()) { - sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, + sendPackagesSuspendedForUser(newSnapshot, Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, modifiedPackages.toArray(new String[0]), modifiedUids.toArray(), userId); } return unmodifiablePackages.toArray(new String[0]); @@ -217,14 +219,14 @@ public final class SuspendPackageHelper { * @return The names of packages which are Unsuspendable. */ @NonNull - String[] getUnsuspendablePackagesForUser(@NonNull Computer computer, + String[] getUnsuspendablePackagesForUser(@NonNull Computer snapshot, @NonNull String[] packageNames, @UserIdInt int userId, int callingUid) { - if (!isSuspendAllowedForUser(userId, callingUid)) { + if (!isSuspendAllowedForUser(snapshot, userId, callingUid)) { Slog.w(TAG, "Cannot suspend due to restrictions on user " + userId); return packageNames; } final ArraySet<String> unactionablePackages = new ArraySet<>(); - final boolean[] canSuspend = canSuspendPackageForUser(computer, packageNames, userId, + final boolean[] canSuspend = canSuspendPackageForUser(snapshot, packageNames, userId, callingUid); for (int i = 0; i < packageNames.length; i++) { if (!canSuspend[i]) { @@ -232,7 +234,7 @@ public final class SuspendPackageHelper { continue; } final PackageStateInternal packageState = - computer.getPackageStateFiltered(packageNames[i], callingUid, userId); + snapshot.getPackageStateFiltered(packageNames[i], callingUid, userId); if (packageState == null) { Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]); unactionablePackages.add(packageNames[i]); @@ -250,8 +252,9 @@ public final class SuspendPackageHelper { * @return The app extras of the suspended package. */ @Nullable - Bundle getSuspendedPackageAppExtras(@NonNull String packageName, int userId, int callingUid) { - final PackageStateInternal ps = mPm.getPackageStateInternal(packageName, callingUid); + Bundle getSuspendedPackageAppExtras(@NonNull Computer snapshot, @NonNull String packageName, + int userId, int callingUid) { + final PackageStateInternal ps = snapshot.getPackageStateInternal(packageName, callingUid); if (ps == null) { return null; } @@ -329,12 +332,14 @@ public final class SuspendPackageHelper { } }); + final Computer newSnapshot = mPm.snapshotComputer(); + mPm.scheduleWritePackageRestrictions(userId); if (!unsuspendedPackages.isEmpty()) { final String[] packageArray = unsuspendedPackages.toArray( new String[unsuspendedPackages.size()]); sendMyPackageSuspendedOrUnsuspended(packageArray, false, userId); - sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_UNSUSPENDED, + sendPackagesSuspendedForUser(newSnapshot, Intent.ACTION_PACKAGES_UNSUSPENDED, packageArray, unsuspendedUids.toArray(), userId); } } @@ -348,10 +353,10 @@ public final class SuspendPackageHelper { * @return The launcher extras. */ @Nullable - Bundle getSuspendedPackageLauncherExtras(@NonNull String packageName, int userId, - int callingUid) { - final PackageStateInternal packageState = mPm.getPackageStateInternal( - packageName, callingUid); + Bundle getSuspendedPackageLauncherExtras(@NonNull Computer snapshot, + @NonNull String packageName, int userId, int callingUid) { + final PackageStateInternal packageState = + snapshot.getPackageStateInternal(packageName, callingUid); if (packageState == null) { return null; } @@ -376,9 +381,10 @@ public final class SuspendPackageHelper { * @param callingUid The caller's uid. * @return {@code true}, if the given package is suspended. */ - boolean isPackageSuspended(@NonNull String packageName, int userId, int callingUid) { - final PackageStateInternal packageState = mPm.getPackageStateInternal( - packageName, callingUid); + boolean isPackageSuspended(@NonNull Computer snapshot, @NonNull String packageName, int userId, + int callingUid) { + final PackageStateInternal packageState = + snapshot.getPackageStateInternal(packageName, callingUid); return packageState != null && packageState.getUserStateOrDefault(userId) .isSuspended(); } @@ -392,8 +398,9 @@ public final class SuspendPackageHelper { * @return The name of suspending package. */ @Nullable - String getSuspendingPackage(@NonNull String suspendedPackage, int userId, int callingUid) { - final PackageStateInternal packageState = mPm.getPackageStateInternal( + String getSuspendingPackage(@NonNull Computer snapshot, @NonNull String suspendedPackage, + int userId, int callingUid) { + final PackageStateInternal packageState = snapshot.getPackageStateInternal( suspendedPackage, callingUid); if (packageState == null) { return null; @@ -424,9 +431,10 @@ public final class SuspendPackageHelper { * @return The dialog info. */ @Nullable - SuspendDialogInfo getSuspendedDialogInfo(@NonNull String suspendedPackage, - @NonNull String suspendingPackage, int userId, int callingUid) { - final PackageStateInternal packageState = mPm.getPackageStateInternal( + SuspendDialogInfo getSuspendedDialogInfo(@NonNull Computer snapshot, + @NonNull String suspendedPackage, @NonNull String suspendingPackage, int userId, + int callingUid) { + final PackageStateInternal packageState = snapshot.getPackageStateInternal( suspendedPackage, callingUid); if (packageState == null) { return null; @@ -454,9 +462,9 @@ public final class SuspendPackageHelper { * @param callingUid The caller's uid. * @return {@code true} if the user is allowed to suspend packages by the caller. */ - boolean isSuspendAllowedForUser(int userId, int callingUid) { + boolean isSuspendAllowedForUser(@NonNull Computer snapshot, int userId, int callingUid) { final UserManagerService userManager = mInjector.getUserManagerService(); - return isCallerDeviceOrProfileOwner(userId, callingUid) + return isCallerDeviceOrProfileOwner(snapshot, userId, callingUid) || (!userManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL, userId) && !userManager.hasUserRestriction(UserManager.DISALLOW_UNINSTALL_APPS, userId)); } @@ -471,21 +479,23 @@ public final class SuspendPackageHelper { * @return An array containing results of the checks */ @NonNull - boolean[] canSuspendPackageForUser(@NonNull Computer computer, @NonNull String[] packageNames, + boolean[] canSuspendPackageForUser(@NonNull Computer snapshot, @NonNull String[] packageNames, int userId, int callingUid) { final boolean[] canSuspend = new boolean[packageNames.length]; - final boolean isCallerOwner = isCallerDeviceOrProfileOwner(userId, callingUid); + final boolean isCallerOwner = isCallerDeviceOrProfileOwner(snapshot, userId, callingUid); final long token = Binder.clearCallingIdentity(); try { final DefaultAppProvider defaultAppProvider = mInjector.getDefaultAppProvider(); final String activeLauncherPackageName = defaultAppProvider.getDefaultHome(userId); final String dialerPackageName = defaultAppProvider.getDefaultDialer(userId); - final String requiredInstallerPackage = getKnownPackageName(PACKAGE_INSTALLER, userId); + final String requiredInstallerPackage = + getKnownPackageName(snapshot, PACKAGE_INSTALLER, userId); final String requiredUninstallerPackage = - getKnownPackageName(PACKAGE_UNINSTALLER, userId); - final String requiredVerifierPackage = getKnownPackageName(PACKAGE_VERIFIER, userId); + getKnownPackageName(snapshot, PACKAGE_UNINSTALLER, userId); + final String requiredVerifierPackage = + getKnownPackageName(snapshot, PACKAGE_VERIFIER, userId); final String requiredPermissionControllerPackage = - getKnownPackageName(PACKAGE_PERMISSION_CONTROLLER, userId); + getKnownPackageName(snapshot, PACKAGE_PERMISSION_CONTROLLER, userId); for (int i = 0; i < packageNames.length; i++) { canSuspend[i] = false; final String packageName = packageNames[i]; @@ -530,7 +540,7 @@ public final class SuspendPackageHelper { + "\": protected package"); continue; } - if (!isCallerOwner && computer.getBlockUninstall(userId, packageName)) { + if (!isCallerOwner && snapshot.getBlockUninstall(userId, packageName)) { Slog.w(TAG, "Cannot suspend package \"" + packageName + "\": blocked by admin"); continue; @@ -539,7 +549,7 @@ public final class SuspendPackageHelper { // Cannot suspend static shared libs as they are considered // a part of the using app (emulating static linking). Also // static libs are installed always on internal storage. - PackageStateInternal packageState = computer.getPackageStateInternal(packageName); + PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); AndroidPackage pkg = packageState == null ? null : packageState.getPkg(); if (pkg != null) { // Cannot suspend SDK libs as they are controlled by SDK manager. @@ -580,8 +590,8 @@ public final class SuspendPackageHelper { * @param userId The user where packages reside. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) - void sendPackagesSuspendedForUser(@NonNull String intent, @NonNull String[] pkgList, - @NonNull int[] uidList, int userId) { + void sendPackagesSuspendedForUser(@NonNull Computer snapshot, @NonNull String intent, + @NonNull String[] pkgList, @NonNull int[] uidList, int userId) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); @@ -592,8 +602,8 @@ public final class SuspendPackageHelper { final String pkgName = pkgList[i]; final int uid = uidList[i]; SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList( - mPm.getPackageStateInternal(pkgName, SYSTEM_UID), - userIds, mPm.getPackageStates()); + snapshot.getPackageStateInternal(pkgName, SYSTEM_UID), + userIds, snapshot.getPackageStates()); if (allowList == null) { allowList = new SparseArray<>(0); } @@ -628,19 +638,22 @@ public final class SuspendPackageHelper { } } - private String getKnownPackageName(@KnownPackage int knownPackage, int userId) { - final String[] knownPackages = mPm.getKnownPackageNamesInternal(knownPackage, userId); + private String getKnownPackageName(@NonNull Computer snapshot, @KnownPackage int knownPackage, + int userId) { + final String[] knownPackages = + mPm.getKnownPackageNamesInternal(snapshot, knownPackage, userId); return knownPackages.length > 0 ? knownPackages[0] : null; } - private boolean isCallerDeviceOrProfileOwner(int userId, int callingUid) { + private boolean isCallerDeviceOrProfileOwner(@NonNull Computer snapshot, int userId, + int callingUid) { if (callingUid == SYSTEM_UID) { return true; } final String ownerPackage = mProtectedPackages.getDeviceOwnerOrProfileOwnerPackage(userId); if (ownerPackage != null) { - return callingUid == mPm.getPackageUidInternal( - ownerPackage, 0, userId, callingUid); + return callingUid == snapshot.getPackageUidInternal(ownerPackage, 0, userId, + callingUid); } return false; } @@ -659,9 +672,10 @@ public final class SuspendPackageHelper { return; } final int[] targetUserIds = new int[] {userId}; + final Computer snapshot = mPm.snapshotComputer(); for (String packageName : affectedPackages) { final Bundle appExtras = suspended - ? getSuspendedPackageAppExtras(packageName, userId, SYSTEM_UID) + ? getSuspendedPackageAppExtras(snapshot, packageName, userId, SYSTEM_UID) : null; final Bundle intentExtras; if (appExtras != null) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index a8d24fad2598..eae7658587f7 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1593,13 +1593,13 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isCredentialSharedWithParent(@UserIdInt int userId) { + public boolean isCredentialSharableWithParent(@UserIdInt int userId) { checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, - "isCredentialSharedWithParent"); + "isCredentialSharableWithParent"); synchronized (mUsersLock) { UserTypeDetails userTypeDetails = getUserTypeDetailsNoChecks(userId); return userTypeDetails != null && userTypeDetails.isProfile() - && userTypeDetails.isCredentialSharedWithParent(); + && userTypeDetails.isCredentialSharableWithParent(); } } @@ -4148,11 +4148,11 @@ public class UserManagerService extends IUserManager.Stub { continue; } if (filter.direction == DefaultCrossProfileIntentFilter.Direction.TO_PARENT) { - mPm.addCrossProfileIntentFilter( + mPm.addCrossProfileIntentFilter(mPm.snapshotComputer(), filter.filter, mContext.getOpPackageName(), profileUserId, parentUserId, filter.flags); } else { - mPm.addCrossProfileIntentFilter( + mPm.addCrossProfileIntentFilter(mPm.snapshotComputer(), filter.filter, mContext.getOpPackageName(), parentUserId, profileUserId, filter.flags); } diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java index 2f5e2388f6a8..4aad1a7f3881 100644 --- a/services/core/java/com/android/server/pm/UserTypeDetails.java +++ b/services/core/java/com/android/server/pm/UserTypeDetails.java @@ -161,7 +161,7 @@ public final class UserTypeDetails { * * <p> Default value is false */ - private final boolean mIsCredentialSharedWithParent; + private final boolean mIsCredentialSharableWithParent; private UserTypeDetails(@NonNull String name, boolean enabled, int maxAllowed, @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, int label, @@ -174,7 +174,7 @@ public final class UserTypeDetails { @Nullable Bundle defaultSecureSettings, @Nullable List<DefaultCrossProfileIntentFilter> defaultCrossProfileIntentFilters, boolean isMediaSharedWithParent, - boolean isCredentialSharedWithParent) { + boolean isCredentialSharableWithParent) { this.mName = name; this.mEnabled = enabled; this.mMaxAllowed = maxAllowed; @@ -194,7 +194,7 @@ public final class UserTypeDetails { this.mBadgeColors = badgeColors; this.mDarkThemeBadgeColors = darkThemeBadgeColors; this.mIsMediaSharedWithParent = isMediaSharedWithParent; - this.mIsCredentialSharedWithParent = isCredentialSharedWithParent; + this.mIsCredentialSharableWithParent = isCredentialSharableWithParent; } /** @@ -323,8 +323,8 @@ public final class UserTypeDetails { * Returns true if the user has shared encryption credential with parent user or * false otherwise. */ - public boolean isCredentialSharedWithParent() { - return mIsCredentialSharedWithParent; + public boolean isCredentialSharableWithParent() { + return mIsCredentialSharableWithParent; } /** Returns a {@link Bundle} representing the default user restrictions. */ @@ -419,7 +419,7 @@ public final class UserTypeDetails { private @DrawableRes int mBadgePlain = Resources.ID_NULL; private @DrawableRes int mBadgeNoBackground = Resources.ID_NULL; private boolean mIsMediaSharedWithParent = false; - private boolean mIsCredentialSharedWithParent = false; + private boolean mIsCredentialSharableWithParent = false; public Builder setName(String name) { mName = name; @@ -521,10 +521,10 @@ public final class UserTypeDetails { /** * Sets shared media property for the user. - * @param isCredentialSharedWithParent the value to be set, true or false + * @param isCredentialSharableWithParent the value to be set, true or false */ - public Builder setIsCredentialSharedWithParent(boolean isCredentialSharedWithParent) { - mIsCredentialSharedWithParent = isCredentialSharedWithParent; + public Builder setIsCredentialSharableWithParent(boolean isCredentialSharableWithParent) { + mIsCredentialSharableWithParent = isCredentialSharableWithParent; return this; } @@ -571,7 +571,7 @@ public final class UserTypeDetails { mDefaultSecureSettings, mDefaultCrossProfileIntentFilters, mIsMediaSharedWithParent, - mIsCredentialSharedWithParent); + mIsCredentialSharableWithParent); } private boolean hasBadge() { diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 1e3b67c394cb..cb18c6d83788 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -122,7 +122,7 @@ public final class UserTypeFactory { .setLabel(0) .setDefaultRestrictions(null) .setIsMediaSharedWithParent(true) - .setIsCredentialSharedWithParent(true); + .setIsCredentialSharableWithParent(true); } /** @@ -154,7 +154,7 @@ public final class UserTypeFactory { .setDefaultRestrictions(getDefaultManagedProfileRestrictions()) .setDefaultSecureSettings(getDefaultManagedProfileSecureSettings()) .setDefaultCrossProfileIntentFilters(getDefaultManagedCrossProfileIntentFilter()) - .setIsCredentialSharedWithParent(true); + .setIsCredentialSharableWithParent(true); } /** diff --git a/services/core/java/com/android/server/pm/VerificationParams.java b/services/core/java/com/android/server/pm/VerificationParams.java index bc936112649f..7423bf65c6a5 100644 --- a/services/core/java/com/android/server/pm/VerificationParams.java +++ b/services/core/java/com/android/server/pm/VerificationParams.java @@ -72,6 +72,7 @@ import android.util.Pair; import android.util.Slog; import com.android.server.DeviceIdleInternal; +import com.android.server.sdksandbox.SdkSandboxManagerLocal; import java.io.File; import java.util.ArrayList; @@ -441,9 +442,22 @@ final class VerificationParams extends HandlerParams { final long verificationTimeout = VerificationUtils.getVerificationTimeout(mPm.mContext, streaming); - final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite, + List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite, receivers.getList(), verificationState); + // Add broadcastReceiver Component to verify Sdk before run in Sdk sandbox. + if (pkgLite.isSdkLibrary) { + if (sufficientVerifiers == null) { + sufficientVerifiers = new ArrayList<>(); + } + ComponentName sdkSandboxComponentName = new ComponentName("android", + SdkSandboxManagerLocal.VERIFIER_RECEIVER); + sufficientVerifiers.add(sdkSandboxComponentName); + + // Add uid of system_server the same uid for SdkSandboxManagerService + verificationState.addSufficientVerifier(Process.myUid()); + } + DeviceIdleInternal idleController = mPm.mInjector.getLocalService(DeviceIdleInternal.class); final BroadcastOptions options = BroadcastOptions.makeBasic(); diff --git a/services/core/java/com/android/server/pm/WatchedIntentFilter.java b/services/core/java/com/android/server/pm/WatchedIntentFilter.java index 30f276e8386a..5d7a2a3bd426 100644 --- a/services/core/java/com/android/server/pm/WatchedIntentFilter.java +++ b/services/core/java/com/android/server/pm/WatchedIntentFilter.java @@ -84,7 +84,7 @@ public class WatchedIntentFilter } // Convert an {@link IntentFilter} to a {@link WatchedIntentFilter} - protected WatchedIntentFilter(IntentFilter f) { + public WatchedIntentFilter(IntentFilter f) { mFilter = new IntentFilter(f); } diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index e28a6ea8ea6b..7e4da945709b 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -31,13 +31,13 @@ import android.content.pm.dex.ArtManagerInternal; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.ISnapshotRuntimeProfileCallback; import android.content.pm.dex.PackageOptimizationInfo; -import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.system.Os; @@ -55,6 +55,7 @@ import com.android.server.pm.Installer; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.PackageManagerServiceCompilerMapping; import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; import dalvik.system.DexFile; import dalvik.system.VMRuntime; @@ -92,7 +93,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { private static final String BOOT_IMAGE_PROFILE_NAME = "android.prof"; private final Context mContext; - private final IPackageManager mPackageManager; + private IPackageManager mPackageManager; private final Object mInstallLock; @GuardedBy("mInstallLock") private final Installer mInstaller; @@ -103,10 +104,9 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { verifyTronLoggingConstants(); } - public ArtManagerService(Context context, IPackageManager pm, Installer installer, + public ArtManagerService(Context context, Installer installer, Object installLock) { mContext = context; - mPackageManager = pm; mInstaller = installer; mInstallLock = installLock; mHandler = new Handler(BackgroundThread.getHandler().getLooper()); @@ -114,6 +114,15 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { LocalServices.addService(ArtManagerInternal.class, new ArtManagerInternalImpl()); } + @NonNull + private IPackageManager getPackageManager() { + if (mPackageManager == null) { + mPackageManager = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + } + return mPackageManager; + } + private boolean checkAndroidPermissions(int callingUid, String callingPackage) { // Callers always need this permission mContext.enforceCallingOrSelfPermission( @@ -157,7 +166,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { } PackageInfo info = null; try { - info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); + info = getPackageManager().getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); } catch (RemoteException ignored) { // Should not happen. } @@ -221,7 +230,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { // TODO(calin): consider adding an API to PMS which can retrieve the // PackageParser.Package. - info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); + info = getPackageManager().getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); } catch (RemoteException ignored) { // Should not happen. } diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 5371454db43c..17109e97ddf1 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -23,6 +23,8 @@ import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo; import static java.util.function.Function.identity; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; @@ -33,6 +35,7 @@ import android.os.BatteryManager; import android.os.FileUtils; import android.os.PowerManager; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; @@ -109,7 +112,7 @@ public class DexManager { // record class loaders or ISAs.) private final DynamicCodeLogger mDynamicCodeLogger; - private final IPackageManager mPackageManager; + private IPackageManager mPackageManager; private final PackageDexOptimizer mPackageDexOptimizer; private final Object mInstallLock; @GuardedBy("mInstallLock") @@ -128,16 +131,22 @@ public class DexManager { private static int DEX_SEARCH_FOUND_SPLIT = 2; // dex file is a split apk private static int DEX_SEARCH_FOUND_SECONDARY = 3; // dex file is a secondary dex - public DexManager(Context context, IPackageManager pms, PackageDexOptimizer pdo, - Installer installer, Object installLock) { + public DexManager(Context context, PackageDexOptimizer pdo, Installer installer, + Object installLock) { + this(context, pdo, installer, installLock, null); + } + + @VisibleForTesting + public DexManager(Context context, PackageDexOptimizer pdo, Installer installer, + Object installLock, @Nullable IPackageManager packageManager) { mContext = context; mPackageCodeLocationsCache = new HashMap<>(); mPackageDexUsage = new PackageDexUsage(); - mPackageManager = pms; mPackageDexOptimizer = pdo; mInstaller = installer; mInstallLock = installLock; - mDynamicCodeLogger = new DynamicCodeLogger(pms, installer); + mDynamicCodeLogger = new DynamicCodeLogger(installer); + mPackageManager = packageManager; // This is currently checked to handle tests that pass in a null context. // TODO(b/174783329): Modify the tests to pass in a mocked Context, PowerManager, @@ -157,6 +166,15 @@ public class DexManager { } } + @NonNull + private IPackageManager getPackageManager() { + if (mPackageManager == null) { + mPackageManager = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + } + return mPackageManager; + } + public DynamicCodeLogger getDynamicCodeLogger() { return mDynamicCodeLogger; } @@ -529,7 +547,7 @@ public class DexManager { PackageInfo pkg; try { - pkg = mPackageManager.getPackageInfo(packageName, /*flags*/0, + pkg = getPackageManager().getPackageInfo(packageName, /*flags*/0, dexUseInfo.getOwnerUserId()); } catch (RemoteException e) { throw new AssertionError(e); @@ -673,7 +691,7 @@ public class DexManager { // to get back the real app uid and its storage kind. These are only used // to perform extra validation in installd. // TODO(calin): maybe a bit overkill. - pkg = mPackageManager.getPackageInfo(packageName, /*flags*/0, + pkg = getPackageManager().getPackageInfo(packageName, /*flags*/0, dexUseInfo.getOwnerUserId()); } catch (RemoteException ignore) { // Can't happen, DexManager is local. diff --git a/services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java b/services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java index 75b4e38e42f5..9b94e993f967 100644 --- a/services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java +++ b/services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java @@ -19,11 +19,13 @@ package com.android.server.pm.dex; import static com.android.server.pm.dex.PackageDynamicCodeLoading.FILE_TYPE_DEX; import static com.android.server.pm.dex.PackageDynamicCodeLoading.FILE_TYPE_NATIVE; +import android.annotation.NonNull; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.os.FileUtils; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.storage.StorageManager; import android.util.EventLog; @@ -58,20 +60,30 @@ public class DynamicCodeLogger { private static final String DCL_DEX_SUBTAG = "dcl"; private static final String DCL_NATIVE_SUBTAG = "dcln"; - private final IPackageManager mPackageManager; + private IPackageManager mPackageManager; private final PackageDynamicCodeLoading mPackageDynamicCodeLoading; private final Installer mInstaller; - DynamicCodeLogger(IPackageManager pms, Installer installer) { - this(pms, installer, new PackageDynamicCodeLoading()); + DynamicCodeLogger(Installer installer) { + mInstaller = installer; + mPackageDynamicCodeLoading = new PackageDynamicCodeLoading(); } @VisibleForTesting - DynamicCodeLogger(IPackageManager pms, Installer installer, - PackageDynamicCodeLoading packageDynamicCodeLoading) { - mPackageManager = pms; - mPackageDynamicCodeLoading = packageDynamicCodeLoading; + DynamicCodeLogger(@NonNull IPackageManager packageManager, @NonNull Installer installer, + @NonNull PackageDynamicCodeLoading packageDynamicCodeLoading) { + mPackageManager = packageManager; mInstaller = installer; + mPackageDynamicCodeLoading = packageDynamicCodeLoading; + } + + @NonNull + private IPackageManager getPackageManager() { + if (mPackageManager == null) { + mPackageManager = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + } + return mPackageManager; } public Set<String> getAllPackagesWithDynamicCodeLoading() { @@ -104,7 +116,7 @@ public class DynamicCodeLogger { try { PackageInfo ownerInfo = - mPackageManager.getPackageInfo(packageName, /*flags*/ 0, userId); + getPackageManager().getPackageInfo(packageName, /*flags*/ 0, userId); appInfo = ownerInfo == null ? null : ownerInfo.applicationInfo; } catch (RemoteException ignored) { // Can't happen, we're local. @@ -167,7 +179,7 @@ public class DynamicCodeLogger { loadingUid = appInfo.uid; } else { try { - loadingUid = mPackageManager.getPackageUid(loadingPackageName, /*flags*/ 0, + loadingUid = getPackageManager().getPackageUid(loadingPackageName, /*flags*/ 0, userId); } catch (RemoteException ignored) { // Can't happen, we're local. @@ -223,7 +235,7 @@ public class DynamicCodeLogger { public void recordNative(int loadingUid, String path) { String[] packages; try { - packages = mPackageManager.getPackagesForUid(loadingUid); + packages = getPackageManager().getPackagesForUid(loadingUid); if (packages == null || packages.length == 0) { return; } diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index a4a200da686b..543e44cce8b6 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -757,12 +757,12 @@ class ActivityClientController extends IActivityClientController.Stub { } @Override - public void setPreferDockBigOverlays(IBinder token, boolean preferDockBigOverlays) { + public void setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays) { final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); - r.setPreferDockBigOverlays(preferDockBigOverlays); + r.setShouldDockBigOverlays(shouldDockBigOverlays); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2153f5f4dd70..677babea4dd4 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -534,7 +534,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // activity can enter picture in picture while pausing (only when switching to another task) PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build(); // The PiP params used when deferring the entering of picture-in-picture. - boolean preferDockBigOverlays; + boolean shouldDockBigOverlays; int launchCount; // count of launches since last state long lastLaunchTime; // time of last launch of this activity ComponentName requestedVrComponent; // the requested component for handling VR mode. @@ -2042,7 +2042,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLetterboxUiController = new LetterboxUiController(mWmService, this); mCameraCompatControlEnabled = mWmService.mContext.getResources() .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled); - preferDockBigOverlays = mWmService.mContext.getResources() + shouldDockBigOverlays = mWmService.mContext.getResources() .getBoolean(R.bool.config_dockBigOverlayWindows); if (_createTime > 0) { @@ -9575,9 +9575,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getTask().getRootTask().onPictureInPictureParamsChanged(); } - void setPreferDockBigOverlays(boolean preferDockBigOverlays) { - this.preferDockBigOverlays = preferDockBigOverlays; - getTask().getRootTask().onPreferDockBigOverlaysChanged(); + void setShouldDockBigOverlays(boolean shouldDockBigOverlays) { + this.shouldDockBigOverlays = shouldDockBigOverlays; + getTask().getRootTask().onShouldDockBigOverlaysChanged(); } @Override diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index ac121a13f308..7d2dfa071597 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2023,22 +2023,12 @@ class ActivityStarter { private boolean canEmbedActivity(@NonNull TaskFragment taskFragment, @NonNull ActivityRecord starting, boolean newTask, Task targetTask) { final Task hostTask = taskFragment.getTask(); - if (hostTask == null) { + // Not allowed embedding a separate task or without host task. + if (hostTask == null || newTask || targetTask != hostTask) { return false; } - // Allowing the embedding if the task is owned by system. - final int hostUid = hostTask.effectiveUid; - if (UserHandle.getAppId(hostUid) == Process.SYSTEM_UID) { - return true; - } - - if (!taskFragment.isAllowedToEmbedActivity(starting)) { - return false; - } - - // Not allowed embedding task. - return !newTask && (targetTask == null || targetTask == hostTask); + return taskFragment.isAllowedToEmbedActivity(starting); } /** diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 8edb3137c416..cd7ebe327c91 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3403,7 +3403,7 @@ class Task extends TaskFragment { info.positionInParent = getRelativePosition(); info.pictureInPictureParams = getPictureInPictureParams(top); - info.preferDockBigOverlays = getPreferDockBigOverlays(); + info.shouldDockBigOverlays = shouldDockBigOverlays(); if (info.pictureInPictureParams != null && info.pictureInPictureParams.isLaunchIntoPip() && top.getTopMostActivity().getLastParentBeforePip() != null) { @@ -3456,9 +3456,9 @@ class Task extends TaskFragment { ? null : new PictureInPictureParams(topMostActivity.pictureInPictureArgs); } - private boolean getPreferDockBigOverlays() { + private boolean shouldDockBigOverlays() { final ActivityRecord topMostActivity = getTopMostActivity(); - return topMostActivity != null && topMostActivity.preferDockBigOverlays; + return topMostActivity != null && topMostActivity.shouldDockBigOverlays; } Rect getDisplayCutoutInsets() { @@ -4354,7 +4354,7 @@ class Task extends TaskFragment { } } - void onPreferDockBigOverlaysChanged() { + void onShouldDockBigOverlaysChanged() { dispatchTaskInfoChangedIfNeeded(true /* force */); } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 3985cbcaa419..597d29f5cd03 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -242,7 +242,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { /** Client assigned unique token for this TaskFragment if this is created by an organizer. */ @Nullable - private IBinder mFragmentToken; + private final IBinder mFragmentToken; /** * Whether to delay the last activity of TaskFragment being immediately removed while finishing. @@ -2392,10 +2392,18 @@ class TaskFragment extends WindowContainer<WindowContainer> { void removeImmediately() { mIsRemovalRequested = false; resetAdjacentTaskFragment(); + cleanUp(); super.removeImmediately(); sendTaskFragmentVanished(); } + /** Called on remove to cleanup. */ + private void cleanUp() { + if (mIsEmbedded) { + mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this); + } + } + @Override Dimmer getDimmer() { // If the window is in an embedded TaskFragment, we want to dim at the TaskFragment. diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 19f921deab4c..bdec49e2ec40 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -140,7 +140,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr mLastSentTaskFragmentInfos.put(tf, info); tf.mTaskFragmentAppearedSent = true; } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentAppeared callback", e); } onTaskFragmentParentInfoChanged(organizer, tf); } @@ -150,7 +150,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr try { organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo()); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentVanished callback", e); } tf.mTaskFragmentAppearedSent = false; mLastSentTaskFragmentInfos.remove(tf); @@ -175,7 +175,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo()); mLastSentTaskFragmentInfos.put(tf, info); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentInfoChanged callback", e); } } @@ -198,7 +198,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig); mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig)); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); } } @@ -210,7 +210,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr try { organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentError callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentError callback", e); } } } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 4c23f3991c58..7f3244796334 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -491,7 +491,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Avoid commit visibility to false here, or else we will get a sudden // "flash" / surface going invisible for a split second. commitVisibility = false; - } else { + } else if (ar.getDeferHidingClient()) { + // Legacy PIP-enter requires pause event with user-leaving. mController.mAtm.mTaskSupervisor.mUserLeaving = true; ar.getTaskFragment().startPausing(false /* uiSleeping */, null /* resuming */, "finishTransition"); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 81344ac31108..d86201294235 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -1470,6 +1470,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return mLaunchTaskFragments.get(tfToken); } + void cleanUpEmbeddedTaskFragment(TaskFragment taskFragment) { + mLaunchTaskFragments.remove(taskFragment.getFragmentToken()); + } + static class CallerInfo { final int mPid; final int mUid; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index fa2850a5157d..c8eaa23ed11d 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -423,6 +423,8 @@ public final class SystemServer implements Dumpable { private static final String SDK_SANDBOX_MANAGER_SERVICE_CLASS = "com.android.server.sdksandbox.SdkSandboxManagerService$Lifecycle"; + private static final String AD_SERVICES_MANAGER_SERVICE_CLASS = + "com.android.server.adservices.AdServicesManagerService$Lifecycle"; private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector"; @@ -2608,6 +2610,11 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(SDK_SANDBOX_MANAGER_SERVICE_CLASS); t.traceEnd(); + // AdServicesManagerService (PP API service) + t.traceBegin("StartAdServicesManagerService"); + mSystemServiceManager.startService(AD_SERVICES_MANAGER_SERVICE_CLASS); + t.traceEnd(); + if (safeMode) { mActivityManagerService.enterSafeMode(); } diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index b0d23a48402c..66e840b5120b 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -235,8 +235,11 @@ public final class ProfcollectForwardingService extends SystemService { // Event observers private void registerObservers() { - registerAppLaunchObserver(); - registerOTAObserver(); + BackgroundThread.get().getThreadHandler().post( + () -> { + registerAppLaunchObserver(); + registerOTAObserver(); + }); } private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver(); diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java index 575e3513eae4..319a769bb1de 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java @@ -19,6 +19,7 @@ package com.android.server.app; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.app.GameServiceProviderInstanceImplTest.FakeGameService.GameServiceState; @@ -26,19 +27,21 @@ import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verifyZeroInteractions; import android.Manifest; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; +import android.app.ActivityManagerInternal; import android.app.ActivityTaskManager; import android.app.IActivityManager; import android.app.IActivityTaskManager; +import android.app.IProcessObserver; import android.app.ITaskStackListener; import android.content.ComponentName; import android.content.Context; @@ -135,6 +138,8 @@ public final class GameServiceProviderInstanceImplTest { private MockitoSession mMockingSession; private GameServiceProviderInstance mGameServiceProviderInstance; @Mock + private ActivityManagerInternal mMockActivityManagerInternal; + @Mock private IActivityTaskManager mMockActivityTaskManager; @Mock private WindowManagerService mMockWindowManagerService; @@ -151,6 +156,7 @@ public final class GameServiceProviderInstanceImplTest { private FakeGameSessionService mFakeGameSessionService; private FakeServiceConnector<IGameSessionService> mFakeGameSessionServiceConnector; private ArrayList<ITaskStackListener> mTaskStackListeners; + private ArrayList<IProcessObserver> mProcessObservers; private ArrayList<TaskSystemBarsListener> mTaskSystemBarsListeners; private ArrayList<RunningTaskInfo> mRunningTaskInfos; @@ -185,6 +191,16 @@ public final class GameServiceProviderInstanceImplTest { return null; }).when(mMockActivityTaskManager).unregisterTaskStackListener(any()); + mProcessObservers = new ArrayList<>(); + doAnswer(invocation -> { + mProcessObservers.add(invocation.getArgument(0)); + return null; + }).when(mMockActivityManager).registerProcessObserver(any()); + doAnswer(invocation -> { + mProcessObservers.remove(invocation.getArgument(0)); + return null; + }).when(mMockActivityManager).unregisterProcessObserver(any()); + mTaskSystemBarsListeners = new ArrayList<>(); doAnswer(invocation -> { mTaskSystemBarsListeners.add(invocation.getArgument(0)); @@ -206,6 +222,7 @@ public final class GameServiceProviderInstanceImplTest { mMockContext, mFakeGameClassifier, mMockActivityManager, + mMockActivityManagerInternal, mMockActivityTaskManager, mMockWindowManagerService, mMockWindowManagerInternal, @@ -429,6 +446,214 @@ public final class GameServiceProviderInstanceImplTest { } @Test + public void gameProcessStopped_soleProcess_destroysGameSession() throws Exception { + int gameProcessId = 1000; + + mGameServiceProviderInstance.start(); + + startTask(10, GAME_A_MAIN_ACTIVITY); + startProcessForPackage(gameProcessId, GAME_A_PACKAGE); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + assertThat(gameSession10.mIsDestroyed).isFalse(); + + // Death of the sole game process destroys the game session. + dispatchProcessDied(gameProcessId); + assertThat(gameSession10.mIsDestroyed).isTrue(); + } + + @Test + public void gameProcessStopped_soleProcess_destroysMultipleGameSessionsForSamePackage() + throws Exception { + int gameProcessId = 1000; + + mGameServiceProviderInstance.start(); + + // Multiple tasks exist for the same package. + startTask(10, GAME_A_MAIN_ACTIVITY); + startTask(11, GAME_A_MAIN_ACTIVITY); + startProcessForPackage(gameProcessId, GAME_A_PACKAGE); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + mFakeGameService.requestCreateGameSession(11); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + FakeGameSession gameSession11 = new FakeGameSession(); + SurfacePackage mockSurfacePackage11 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(11) + .complete(new CreateGameSessionResult(gameSession11, mockSurfacePackage11)); + + assertThat(gameSession10.mIsDestroyed).isFalse(); + assertThat(gameSession11.mIsDestroyed).isFalse(); + + // Death of the sole game process destroys both game sessions. + dispatchProcessDied(gameProcessId); + assertThat(gameSession10.mIsDestroyed).isTrue(); + assertThat(gameSession11.mIsDestroyed).isTrue(); + } + + @Test + public void gameProcessStopped_multipleProcesses_gameSessionDestroyedWhenAllDead() + throws Exception { + int firstGameProcessId = 1000; + int secondGameProcessId = 1001; + + mGameServiceProviderInstance.start(); + + startTask(10, GAME_A_MAIN_ACTIVITY); + startProcessForPackage(firstGameProcessId, GAME_A_PACKAGE); + startProcessForPackage(secondGameProcessId, GAME_A_PACKAGE); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + assertThat(gameSession10.mIsDestroyed).isFalse(); + + // Death of the first process (with the second one still alive) does not destroy the game + // session. + dispatchProcessDied(firstGameProcessId); + assertThat(gameSession10.mIsDestroyed).isFalse(); + + // Death of the second process does destroy the game session. + dispatchProcessDied(secondGameProcessId); + assertThat(gameSession10.mIsDestroyed).isTrue(); + } + + @Test + public void gameProcessCreatedAfterInitialProcessDead_newGameSessionCreated() throws Exception { + int firstGameProcessId = 1000; + int secondGameProcessId = 1000; + + mGameServiceProviderInstance.start(); + + startTask(10, GAME_A_MAIN_ACTIVITY); + startProcessForPackage(firstGameProcessId, GAME_A_PACKAGE); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + assertThat(gameSession10.mIsDestroyed).isFalse(); + + // After the first game process dies, the game session should be destroyed. + dispatchProcessDied(firstGameProcessId); + assertThat(gameSession10.mIsDestroyed).isTrue(); + + // However, when a new process for the game starts, a new game session should be created. + startProcessForPackage(secondGameProcessId, GAME_A_PACKAGE); + // Verify that a new pending game session is created for the game's taskId. + assertNotNull(mFakeGameSessionService.removePendingFutureForTaskId(10)); + } + + @Test + public void gameProcessCreatedAfterInitialProcessDead_multipleGameSessionsCreatedSamePackage() + throws Exception { + int firstGameProcessId = 1000; + int secondGameProcessId = 1000; + + mGameServiceProviderInstance.start(); + + // Multiple tasks exist for the same package. + startTask(10, GAME_A_MAIN_ACTIVITY); + startTask(11, GAME_A_MAIN_ACTIVITY); + startProcessForPackage(firstGameProcessId, GAME_A_PACKAGE); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + + mFakeGameService.requestCreateGameSession(10); + mFakeGameService.requestCreateGameSession(11); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + FakeGameSession gameSession11 = new FakeGameSession(); + SurfacePackage mockSurfacePackage11 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(11) + .complete(new CreateGameSessionResult(gameSession11, mockSurfacePackage11)); + + assertThat(gameSession10.mIsDestroyed).isFalse(); + assertThat(gameSession11.mIsDestroyed).isFalse(); + + // After the first game process dies, both game sessions for the package should be + // destroyed. + dispatchProcessDied(firstGameProcessId); + assertThat(gameSession10.mIsDestroyed).isTrue(); + assertThat(gameSession11.mIsDestroyed).isTrue(); + + // However, when a new process for the game starts, new game sessions for the same + // package should be created. + startProcessForPackage(secondGameProcessId, GAME_A_PACKAGE); + // Verify that new pending game sessions were created for each of the game's taskIds. + assertNotNull(mFakeGameSessionService.removePendingFutureForTaskId(10)); + assertNotNull(mFakeGameSessionService.removePendingFutureForTaskId(11)); + } + + @Test + public void gameProcessStarted_gameSessionNotRequested_doesNothing() throws Exception { + int gameProcessId = 1000; + + mGameServiceProviderInstance.start(); + + // A game task and process are started, but requestCreateGameSession is never called. + startTask(10, GAME_A_MAIN_ACTIVITY); + startProcessForPackage(gameProcessId, GAME_A_PACKAGE); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + + // No game session should be created. + assertThat(mFakeGameSessionService.getCapturedCreateInvocations()).isEmpty(); + } + + @Test + public void processActivityAndDeath_notForGame_gameSessionUnaffected() throws Exception { + mGameServiceProviderInstance.start(); + + startTask(10, GAME_A_MAIN_ACTIVITY); + + mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + + // Process activity for a process without a known package is ignored. + startProcessForPackage(1000, /*packageName=*/ null); + dispatchProcessActivity(1000); + dispatchProcessDied(1000); + + // Process activity for a process with a different package is ignored + startProcessForPackage(1001, GAME_B_PACKAGE); + dispatchProcessActivity(1001); + dispatchProcessDied(1001); + + // Death of a process for which there was no activity is ignored + dispatchProcessDied(1002); + + // Despite all the process activity and death, the game session is not destroyed. + assertThat(gameSession10.mIsDestroyed).isFalse(); + } + + @Test public void taskSystemBarsListenerChanged_noAssociatedGameSession_doesNothing() { mGameServiceProviderInstance.start(); @@ -900,7 +1125,8 @@ public final class GameServiceProviderInstanceImplTest { mFakeGameSessionService.getCapturedCreateInvocations()) .mGameSessionController.restartGame(11); - verifyZeroInteractions(mMockActivityManager); + verify(mMockActivityManager).registerProcessObserver(any()); + verifyNoMoreInteractions(mMockActivityManager); assertThat(mMockContext.getLastStartedIntent()).isNull(); } @@ -932,7 +1158,6 @@ public final class GameServiceProviderInstanceImplTest { dispatchTaskRemoved(taskId); } - private void dispatchTaskRemoved(int taskId) { dispatchTaskChangeEvent(taskStackListener -> { taskStackListener.onTaskRemoved(taskId); @@ -958,6 +1183,37 @@ public final class GameServiceProviderInstanceImplTest { } } + private void startProcessForPackage(int processId, @Nullable String packageName) { + if (packageName != null) { + when(mMockActivityManagerInternal.getPackageNameByPid(processId)).thenReturn( + packageName); + } + + dispatchProcessActivity(processId); + } + + private void dispatchProcessActivity(int processId) { + dispatchProcessChangedEvent(processObserver -> { + // Neither uid nor foregroundActivities are used by the implementation being tested. + processObserver.onForegroundActivitiesChanged(processId, /*uid=*/ + 0, /*foregroundActivities=*/ false); + }); + } + + private void dispatchProcessDied(int processId) { + dispatchProcessChangedEvent(processObserver -> { + // The uid param is not used by the implementation being tested. + processObserver.onProcessDied(processId, /*uid=*/ 0); + }); + } + + private void dispatchProcessChangedEvent( + ThrowingConsumer<IProcessObserver> processObserverConsumer) { + for (IProcessObserver processObserver : mProcessObservers) { + processObserverConsumer.accept(processObserver); + } + } + private void mockPermissionGranted(String permission) { mMockContext.setPermission(permission, PackageManager.PERMISSION_GRANTED); } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java index 8223b8c86c5b..6f503c7dd941 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java @@ -116,7 +116,7 @@ public final class BackgroundDexOptServiceUnitTest { when(mInjector.getDataDirStorageLowBytes()).thenReturn(STORAGE_LOW_BYTES); when(mInjector.getDexOptThermalCutoff()).thenReturn(PowerManager.THERMAL_STATUS_CRITICAL); when(mInjector.getCurrentThermalStatus()).thenReturn(PowerManager.THERMAL_STATUS_NONE); - when(mDexOptHelper.getOptimizablePackages()).thenReturn(DEFAULT_PACKAGE_LIST); + when(mDexOptHelper.getOptimizablePackages(any())).thenReturn(DEFAULT_PACKAGE_LIST); when(mDexOptHelper.performDexOptWithStatus(any())).thenReturn( PackageDexOptimizer.DEX_OPT_PERFORMED); @@ -158,7 +158,7 @@ public final class BackgroundDexOptServiceUnitTest { @Test public void testNoExecutionForNoOptimizablePackages() { initUntilBootCompleted(); - when(mDexOptHelper.getOptimizablePackages()).thenReturn(EMPTY_PACKAGE_LIST); + when(mDexOptHelper.getOptimizablePackages(any())).thenReturn(EMPTY_PACKAGE_LIST); assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isFalse(); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt index 13199032a223..537a0280e24b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt @@ -157,7 +157,7 @@ class PackageManagerServiceHibernationTests { rule.system().validateFinalState() whenever(appHibernationManager.isHibernatingGlobally(TEST_PACKAGE_2_NAME)).thenReturn(true) - val optimizablePkgs = DexOptHelper(pm).optimizablePackages + val optimizablePkgs = DexOptHelper(pm).getOptimizablePackages(pm.snapshotComputer()) assertTrue(optimizablePkgs.contains(TEST_PACKAGE_NAME)) assertFalse(optimizablePkgs.contains(TEST_PACKAGE_2_NAME)) diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt index b063d22de2bb..1515282812c2 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt @@ -85,6 +85,7 @@ class SharedLibrariesImplTest { private lateinit var mSharedLibrariesImpl: SharedLibrariesImpl private lateinit var mPms: PackageManagerService private lateinit var mSettings: Settings + private lateinit var mComputer: Computer @Mock private lateinit var mDeletePackageHelper: DeletePackageHelper @@ -114,22 +115,16 @@ class SharedLibrariesImplTest { mSharedLibrariesImpl.setDeletePackageHelper(mDeletePackageHelper) addExistingSharedLibraries() + mComputer = mock { + whenever(sharedLibraries) { mSharedLibrariesImpl.sharedLibraries } + whenever(resolveInternalPackageName(anyString(), anyLong())) { arguments[0] } + } + whenever(mSettings.getPackageLPr(any())) { mExistingSettings[arguments[0]] } whenever(mRule.mocks().injector.getSystemService(StorageManager::class.java)) .thenReturn(mStorageManager) whenever(mStorageManager.findPathForUuid(nullable())).thenReturn(mFile) - doAnswer { it.arguments[0] }.`when`(mPms).resolveInternalPackageName(any(), any()) - doAnswer { - mockThrowOnUnmocked<Computer> { - whenever(sharedLibraries) { mSharedLibrariesImpl.sharedLibraries } - whenever(resolveInternalPackageName(anyString(), anyLong())) { - mPms.resolveInternalPackageName(getArgument(0), getArgument(1)) - } - whenever(getPackageStateInternal(anyString())) { - mPms.getPackageStateInternal(getArgument(0)) - } - } - }.`when`(mPms).snapshotComputer() + doAnswer { mComputer }.`when`(mPms).snapshotComputer() whenever(mDeletePackageHelper.deletePackageX(any(), any(), any(), any(), any())) .thenReturn(PackageManager.DELETE_SUCCEEDED) whenever(mRule.mocks().injector.compatibility).thenReturn(mPlatformCompat) @@ -189,7 +184,8 @@ class SharedLibrariesImplTest { @Test fun removeSharedLibrary() { - doAnswer { mutableListOf(VersionedPackage(CONSUMER_PACKAGE_NAME, 1L)) }.`when`(mPms) + doAnswer { mutableListOf(VersionedPackage(CONSUMER_PACKAGE_NAME, 1L)) } + .`when`(mComputer) .getPackagesUsingSharedLibrary(any(), any(), any(), any()) val staticInfo = mSharedLibrariesImpl .getSharedLibraryInfo(STATIC_LIB_NAME, STATIC_LIB_VERSION)!! 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 5230ea7304c8..4818573e9ae5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt @@ -104,9 +104,9 @@ class SuspendPackageHelperTest { pms, rule.mocks().injector, broadcastHelper, protectedPackages) defaultAppProvider = rule.mocks().defaultAppProvider testHandler = rule.mocks().handler - packageSetting1 = pms.getPackageStateInternal(TEST_PACKAGE_1)!! - packageSetting2 = pms.getPackageStateInternal(TEST_PACKAGE_2)!! - ownerSetting = pms.getPackageStateInternal(DEVICE_OWNER_PACKAGE)!! + packageSetting1 = pms.snapshotComputer().getPackageStateInternal(TEST_PACKAGE_1)!! + packageSetting2 = pms.snapshotComputer().getPackageStateInternal(TEST_PACKAGE_2)!! + ownerSetting = pms.snapshotComputer().getPackageStateInternal(DEVICE_OWNER_PACKAGE)!! deviceOwnerUid = UserHandle.getUid(TEST_USER_ID, ownerSetting.appId) packagesToSuspend = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) uidsToSuspend = intArrayOf(packageSetting1.appId, packageSetting2.appId) @@ -270,7 +270,7 @@ class SuspendPackageHelperTest { testHandler.flush() assertThat(failedNames).isEmpty() - val result = suspendPackageHelper.getSuspendedPackageAppExtras( + val result = suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(), TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)!! assertThat(result.getString(TEST_PACKAGE_1)).isEqualTo(TEST_PACKAGE_1) @@ -286,13 +286,13 @@ class SuspendPackageHelperTest { null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() - assertThat(suspendPackageHelper.getSuspendingPackage( + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE) - assertThat(suspendPackageHelper.getSuspendingPackage( + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE) - assertThat(suspendPackageHelper.getSuspendedPackageAppExtras( + assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(), TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isNotNull() - assertThat(suspendPackageHelper.getSuspendedPackageAppExtras( + assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(), TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNotNull() suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(), @@ -311,13 +311,13 @@ class SuspendPackageHelperTest { nullable(), nullable(), any(), eq(TEST_PACKAGE_2), nullable(), any(), any(), nullable(), nullable()) - assertThat(suspendPackageHelper.getSuspendingPackage( + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isNull() - assertThat(suspendPackageHelper.getSuspendingPackage( + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNull() - assertThat(suspendPackageHelper.getSuspendedPackageAppExtras( + assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(), TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isNull() - assertThat(suspendPackageHelper.getSuspendedPackageAppExtras( + assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(pms.snapshotComputer(), TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNull() } @@ -331,7 +331,7 @@ class SuspendPackageHelperTest { testHandler.flush() assertThat(failedNames).isEmpty() - val result = suspendPackageHelper.getSuspendedPackageLauncherExtras( + val result = suspendPackageHelper.getSuspendedPackageLauncherExtras(pms.snapshotComputer(), TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)!! assertThat(result.getString(TEST_PACKAGE_2)).isEqualTo(TEST_PACKAGE_2) @@ -346,7 +346,7 @@ class SuspendPackageHelperTest { testHandler.flush() assertThat(failedNames).isEmpty() - assertThat(suspendPackageHelper.isPackageSuspended( + assertThat(suspendPackageHelper.isPackageSuspended(pms.snapshotComputer(), TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid)).isTrue() } @@ -360,7 +360,7 @@ class SuspendPackageHelperTest { testHandler.flush() assertThat(failedNames).isEmpty() - assertThat(suspendPackageHelper.getSuspendingPackage( + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE) } @@ -375,7 +375,7 @@ class SuspendPackageHelperTest { testHandler.flush() assertThat(failedNames).isEmpty() - val result = suspendPackageHelper.getSuspendedDialogInfo( + val result = suspendPackageHelper.getSuspendedDialogInfo(pms.snapshotComputer(), TEST_PACKAGE_1, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)!! assertThat(result.title).isEqualTo(TEST_PACKAGE_1) @@ -387,8 +387,8 @@ class SuspendPackageHelperTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, allowList(10001, 10002, 10003)) - suspendPackageHelper.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, - packagesToSuspend, uidsToSuspend, TEST_USER_ID) + suspendPackageHelper.sendPackagesSuspendedForUser(pms.snapshotComputer(), + Intent.ACTION_PACKAGES_SUSPENDED, packagesToSuspend, uidsToSuspend, TEST_USER_ID) testHandler.flush() verify(broadcastHelper).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), any(), nullable()) @@ -406,8 +406,8 @@ class SuspendPackageHelperTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, allowList(10001, 10002, 10007)) - suspendPackageHelper.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, - packagesToSuspend, uidsToSuspend, TEST_USER_ID) + suspendPackageHelper.sendPackagesSuspendedForUser(pms.snapshotComputer(), + Intent.ACTION_PACKAGES_SUSPENDED, packagesToSuspend, uidsToSuspend, TEST_USER_ID) testHandler.flush() verify(broadcastHelper, times(2)).sendPackageBroadcast( any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), @@ -429,8 +429,8 @@ class SuspendPackageHelperTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, null) - suspendPackageHelper.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, - packagesToSuspend, uidsToSuspend, TEST_USER_ID) + suspendPackageHelper.sendPackagesSuspendedForUser(pms.snapshotComputer(), + Intent.ACTION_PACKAGES_SUSPENDED, packagesToSuspend, uidsToSuspend, TEST_USER_ID) testHandler.flush() verify(broadcastHelper, times(2)).sendPackageBroadcast( any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), @@ -449,8 +449,9 @@ class SuspendPackageHelperTest { @Test @Throws(Exception::class) fun sendPackagesSuspendModifiedForUser() { - suspendPackageHelper.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, - packagesToSuspend, uidsToSuspend, TEST_USER_ID) + suspendPackageHelper.sendPackagesSuspendedForUser(pms.snapshotComputer(), + Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, packagesToSuspend, uidsToSuspend, + TEST_USER_ID) testHandler.flush() verify(broadcastHelper).sendPackageBroadcast( eq(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED), nullable(), bundleCaptor.capture(), @@ -483,13 +484,13 @@ class SuspendPackageHelperTest { Mockito.doReturn(DIALER_PACKAGE).`when`(defaultAppProvider) .getDefaultDialer(eq(TEST_USER_ID)) Mockito.doReturn(arrayOf(INSTALLER_PACKAGE)).`when`(pms).getKnownPackageNamesInternal( - eq(PackageManagerInternal.PACKAGE_INSTALLER), eq(TEST_USER_ID)) + any(), eq(PackageManagerInternal.PACKAGE_INSTALLER), eq(TEST_USER_ID)) Mockito.doReturn(arrayOf(UNINSTALLER_PACKAGE)).`when`(pms).getKnownPackageNamesInternal( - eq(PackageManagerInternal.PACKAGE_UNINSTALLER), eq(TEST_USER_ID)) + any(), eq(PackageManagerInternal.PACKAGE_UNINSTALLER), eq(TEST_USER_ID)) Mockito.doReturn(arrayOf(VERIFIER_PACKAGE)).`when`(pms).getKnownPackageNamesInternal( - eq(PackageManagerInternal.PACKAGE_VERIFIER), eq(TEST_USER_ID)) + any(), eq(PackageManagerInternal.PACKAGE_VERIFIER), eq(TEST_USER_ID)) Mockito.doReturn(arrayOf(PERMISSION_CONTROLLER_PACKAGE)).`when`(pms) - .getKnownPackageNamesInternal( + .getKnownPackageNamesInternal(any(), eq(PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER), eq(TEST_USER_ID)) } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java index 8abe46fab1d6..9d269719db64 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -159,8 +159,8 @@ public class DexManagerTests { .when(mockContext) .getSystemService(PowerManager.class); - mDexManager = new DexManager(mockContext, mPM, /*PackageDexOptimizer*/ null, - mInstaller, mInstallLock); + mDexManager = new DexManager(mockContext, /*PackageDexOptimizer*/ null, + mInstaller, mInstallLock, mPM); // Foo and Bar are available to user0. // Only Bar is available to user1; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 21c09a09e10f..1d10b8aa3f5a 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -217,7 +217,7 @@ public class LockSettingsServiceTestable extends LockSettingsService { } @Override - protected boolean isCredentialSharedWithParent(int userId) { + protected boolean isCredentialSharableWithParent(int userId) { UserInfo userInfo = mUserManager.getUserInfo(userId); return userInfo.isCloneProfile() || userInfo.isManagedProfile(); } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index 050b224bf7f7..946108d607db 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -23,11 +23,10 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; import static java.lang.reflect.Modifier.isFinal; -import static java.lang.reflect.Modifier.isPrivate; -import static java.lang.reflect.Modifier.isProtected; 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; @@ -63,7 +62,6 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; @@ -101,7 +99,7 @@ public class PackageManagerServiceTest { @Nullable Bundle bOptions) { } - public void sendPackageAddedForNewUsers(String packageName, + public void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName, boolean sendBootComplete, boolean includeStopped, int appId, int[] userIds, int[] instantUserIds, int dataLoaderType) { } @@ -456,147 +454,6 @@ public class PackageManagerServiceTest { return null; } - // Return the boolean locked value. A null return means the annotation was not - // found. This method will fail if the annotation is found but is not one of the - // known constants. - private Boolean getOverride(Method m) { - final String name = "Computer." + displayName(m); - final Computer.LiveImplementation annotation = - m.getAnnotation(Computer.LiveImplementation.class); - if (annotation == null) { - return null; - } - final int override = annotation.override(); - if (override == Computer.LiveImplementation.MANDATORY) { - return true; - } else if (override == Computer.LiveImplementation.NOT_ALLOWED) { - return false; - } else { - flag(name, "invalid Live value: " + override); - return null; - } - } - - @Test - public void testComputerStructure() { - // Verify that Copmuter methods are properly annotated and that ComputerLocked is - // properly populated per annotations. - // Call PackageManagerService.validateComputer(); - Class base = Computer.class; - - HashMap<Method, Boolean> methodType = new HashMap<>(); - - // Verify that all Computer methods are annotated and that the annotation - // parameter locked() is valid. - for (Method m : base.getDeclaredMethods()) { - final String name = "Computer." + displayName(m); - Boolean override = getOverride(m); - if (override == null) { - flag(name, "missing required Live annotation"); - } - methodType.put(m, override); - } - - Class coreClass = ComputerEngine.class; - final Method[] coreMethods = coreClass.getDeclaredMethods(); - - // Examine every method in the core. If it inherits from a base method it must be - // "public final" if the base is NOT_ALLOWED or "public" if the base is MANDATORY. - // If the core method does not inherit from the base then it must be either - // private or protected. - for (Method m : base.getDeclaredMethods()) { - String name = "Computer." + displayName(m); - final boolean locked = methodType.get(m); - final Method core = matchMethod(m, coreMethods); - if (core == null) { - flag(name, "not overridden in ComputerEngine"); - continue; - } - name = "ComputerEngine." + displayName(m); - final int modifiers = core.getModifiers(); - if (!locked) { - if (!isPublic(modifiers)) { - flag(name, "is not public"); - } - if (!isFinal(modifiers)) { - flag(name, "is not final"); - } - } - } - // Any methods left in the coreMethods array must be private or protected. - // Protected methods must be overridden (and final) in the live list. - Method[] coreHelpers = new Method[coreMethods.length]; - int coreIndex = 0; - for (Method m : coreMethods) { - if (m != null) { - final String name = "ComputerEngine." + displayName(m); - if (name.contains(".lambda$static")) { - // skip static lambda function - continue; - } - - final int modifiers = m.getModifiers(); - if (isPrivate(modifiers)) { - // Okay - } else if (isProtected(modifiers)) { - coreHelpers[coreIndex++] = m; - } else { - flag(name, "is neither private nor protected"); - } - } - } - - Class liveClass = ComputerLocked.class; - final Method[] liveMethods = liveClass.getDeclaredMethods(); - - // Examine every method in the live list. Every method must be final and must - // inherit either from base or core. If the method inherits from a base method - // then the base must be MANDATORY. - for (Method m : base.getDeclaredMethods()) { - String name = "Computer." + displayName(m); - final boolean locked = methodType.get(m); - final Method live = matchMethod(m, liveMethods); - if (live == null) { - if (locked) { - flag(name, "not overridden in ComputerLocked"); - } - continue; - } - if (!locked) { - flag(name, "improperly overridden in ComputerLocked"); - continue; - } - - name = "ComputerLocked." + displayName(m); - final int modifiers = live.getModifiers(); - if (!locked) { - if (!isPublic(modifiers)) { - flag(name, "is not public"); - } - if (!isFinal(modifiers)) { - flag(name, "is not final"); - } - } - } - for (Method m : coreHelpers) { - if (m == null) { - continue; - } - String name = "ComputerLocked." + displayName(m); - final Method live = matchMethod(m, liveMethods); - if (live == null) { - flag(name, "is not overridden in ComputerLocked"); - continue; - } - } - for (Method m : liveMethods) { - if (m != null) { - String name = "ComputerLocked." + displayName(m); - flag(name, "illegal local method"); - } - } - } - private static PerPackageReadTimeouts[] getPerPackageReadTimeouts(String knownDigestersList) { final String defaultTimeouts = "3600000001:3600000002:3600000003"; List<PerPackageReadTimeouts> result = PerPackageReadTimeouts.parseDigestersList( diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 2b34bc2ef28d..f4ab3db3c917 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -31,11 +31,11 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.annotation.NonNull; @@ -1103,6 +1103,59 @@ public class PackageManagerSettingsTests { assertThat(countDownLatch.getCount(), is(0L)); } + @Test + public void testRegisterAndRemoveAppId() throws PackageManagerException { + // Test that the first new app UID should start from FIRST_APPLICATION_UID + final Settings settings = makeSettings(); + final PackageSetting ps = createPackageSetting("com.foo"); + assertTrue(settings.registerAppIdLPw(ps, false)); + assertEquals(10000, ps.getAppId()); + // Set up existing app IDs: 10000, 10001, 10003 + final PackageSetting ps1 = createPackageSetting("com.foo1"); + ps1.setAppId(10001); + final PackageSetting ps2 = createPackageSetting("com.foo2"); + ps2.setAppId(10003); + final PackageSetting ps3 = createPackageSetting("com.foo3"); + assertEquals(0, ps3.getAppId()); + assertTrue(settings.registerAppIdLPw(ps1, false)); + assertTrue(settings.registerAppIdLPw(ps2, false)); + assertTrue(settings.registerAppIdLPw(ps3, false)); + assertEquals(10001, ps1.getAppId()); + assertEquals(10003, ps2.getAppId()); + // Expecting the new one to start with the next available uid + assertEquals(10002, ps3.getAppId()); + // Remove and insert a new one and the new one should not reuse the same uid + settings.removeAppIdLPw(10002); + final PackageSetting ps4 = createPackageSetting("com.foo4"); + assertTrue(settings.registerAppIdLPw(ps4, false)); + assertEquals(10004, ps4.getAppId()); + // Keep adding more + final PackageSetting ps5 = createPackageSetting("com.foo5"); + assertTrue(settings.registerAppIdLPw(ps5, false)); + assertEquals(10005, ps5.getAppId()); + // Remove the last one and the new one should use incremented uid + settings.removeAppIdLPw(10005); + final PackageSetting ps6 = createPackageSetting("com.foo6"); + assertTrue(settings.registerAppIdLPw(ps6, false)); + assertEquals(10006, ps6.getAppId()); + } + + /** + * Test replacing a PackageSetting with a SharedUserSetting in mAppIds + */ + @Test + public void testAddPackageSetting() throws PackageManagerException { + final Settings settings = makeSettings(); + final SharedUserSetting sus1 = new SharedUserSetting( + "TestUser", 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/); + sus1.mAppId = 10001; + final PackageSetting ps1 = createPackageSetting("com.foo"); + ps1.setAppId(10001); + assertTrue(settings.registerAppIdLPw(ps1, false)); + settings.addPackageSettingLPw(ps1, sus1); + assertSame(sus1, settings.getSharedUserSettingLPr(ps1)); + } + private void verifyUserState(PackageUserState userState, boolean notLaunched, boolean stopped, boolean installed) { assertThat(userState.getEnabledState(), is(0)); diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java index 18d3f3d0e805..1ce957d1e768 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -489,6 +489,7 @@ public class AppStandbyControllerTests { @Before public void setUp() throws Exception { + LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); LocalServices.addService( UsageStatsManagerInternal.class, mock(UsageStatsManagerInternal.class)); MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 0debdfa3bd1a..c6158662d110 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -359,17 +359,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() throws RemoteException { mController.registerOrganizer(mIOrganizer); - final ActivityRecord activity = createActivityRecord(mDisplayContent); - final int uid = Binder.getCallingUid(); - activity.info.applicationInfo.uid = uid; - activity.getTask().effectiveUid = uid; + final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent); final IBinder fragmentToken = new Binder(); - final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder( - mOrganizerToken, fragmentToken, activity.token).build(); - mOrganizer.applyTransaction(mTransaction); // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. - mTransaction.createTaskFragment(params); + createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken); mTransaction.startActivityInTaskFragment( mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */); mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class)); @@ -381,7 +375,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final TaskFragment taskFragment = mAtm.mWindowOrganizerController .getTaskFragment(fragmentToken); assertNotNull(taskFragment); - assertEquals(activity.getTask(), taskFragment.getTask()); + assertEquals(ownerActivity.getTask(), taskFragment.getTask()); } @Test @@ -523,4 +517,43 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { mController.dispatchPendingEvents(); verify(mOrganizer).onTaskFragmentInfoChanged(any()); } + + /** + * When an embedded {@link TaskFragment} is removed, we should clean up the reference in the + * {@link WindowOrganizerController}. + */ + @Test + public void testTaskFragmentRemoved_cleanUpEmbeddedTaskFragment() + throws RemoteException { + mController.registerOrganizer(mIOrganizer); + final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent); + final IBinder fragmentToken = new Binder(); + createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken); + mAtm.getWindowOrganizerController().applyTransaction(mTransaction); + final TaskFragment taskFragment = mAtm.mWindowOrganizerController + .getTaskFragment(fragmentToken); + + assertNotNull(taskFragment); + + taskFragment.removeImmediately(); + + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + } + + /** + * Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls + * {@link WindowOrganizerController#applyTransaction} to apply the transaction, + */ + private void createTaskFragmentFromOrganizer(WindowContainerTransaction wct, + ActivityRecord ownerActivity, IBinder fragmentToken) { + final int uid = Binder.getCallingUid(); + ownerActivity.info.applicationInfo.uid = uid; + ownerActivity.getTask().effectiveUid = uid; + final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder( + mOrganizerToken, fragmentToken, ownerActivity.token).build(); + mOrganizer.applyTransaction(wct); + + // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. + wct.createTaskFragment(params); + } } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 27d423b3bc1e..bce6809ef32d 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -3171,9 +3171,14 @@ public abstract class ConnectionService extends Service { * * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, android.os.Bundle)}. * + * @param connectionManagerPhoneAccount The connection manager account to use for managing + * this call + * @param request Details about the outgoing call + * @return The {@code Connection} object to satisfy this call, or the result of an invocation + * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call * @hide */ - @SystemApi + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public @Nullable Connection onCreateUnknownConnection( @NonNull PhoneAccountHandle connectionManagerPhoneAccount, diff --git a/tests/TrustTests/AndroidManifest.xml b/tests/TrustTests/AndroidManifest.xml index c94152da2bf6..68bc1f69628f 100644 --- a/tests/TrustTests/AndroidManifest.xml +++ b/tests/TrustTests/AndroidManifest.xml @@ -23,7 +23,9 @@ <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> + <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> + <uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" /> <uses-permission android:name="android.permission.TRUST_LISTENER" /> diff --git a/tests/TrustTests/src/android/trust/test/LockUserTest.kt b/tests/TrustTests/src/android/trust/test/LockUserTest.kt index 83fc28fee818..8f200a64450e 100644 --- a/tests/TrustTests/src/android/trust/test/LockUserTest.kt +++ b/tests/TrustTests/src/android/trust/test/LockUserTest.kt @@ -25,7 +25,6 @@ import android.util.Log import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.rules.RuleChain @@ -49,7 +48,6 @@ class LockUserTest { .around(lockStateTrackingRule) .around(trustAgentRule) - @Ignore("Causes issues with subsequent tests") // TODO: Enable test @Test fun lockUser_locksTheDevice() { Log.i(TAG, "Locking user") diff --git a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt index bc100ba03639..006525d857ac 100644 --- a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt @@ -20,6 +20,8 @@ import android.content.Context import android.util.Log import android.view.WindowManagerGlobal import androidx.test.core.app.ApplicationProvider.getApplicationContext +import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation +import androidx.test.uiautomator.UiDevice import com.android.internal.widget.LockPatternUtils import com.android.internal.widget.LockscreenCredential import com.google.common.truth.Truth.assertWithMessage @@ -32,6 +34,7 @@ import org.junit.runners.model.Statement */ class ScreenLockRule : TestRule { private val context: Context = getApplicationContext() + private val uiDevice = UiDevice.getInstance(getInstrumentation()) private val windowManager = WindowManagerGlobal.getWindowManagerService() private val lockPatternUtils = LockPatternUtils(context) private var instantLockSavedValue = false @@ -48,19 +51,21 @@ class ScreenLockRule : TestRule { } finally { removeScreenLock() revertLockOnPowerButton() + verifyKeyguardDismissed() } } } private fun verifyNoScreenLockAlreadySet() { assertWithMessage("Screen Lock must not already be set on device") - .that(lockPatternUtils.isSecure(context.userId)) - .isFalse() + .that(lockPatternUtils.isSecure(context.userId)) + .isFalse() } private fun verifyKeyguardDismissed() { val maxWaits = 30 var waitCount = 0 + while (windowManager.isKeyguardLocked && waitCount < maxWaits) { Log.i(TAG, "Keyguard still showing; attempting to dismiss and wait 50ms ($waitCount)") windowManager.dismissKeyguard(null, null) @@ -68,19 +73,19 @@ class ScreenLockRule : TestRule { waitCount++ } assertWithMessage("Keyguard should be unlocked") - .that(windowManager.isKeyguardLocked) - .isFalse() + .that(windowManager.isKeyguardLocked) + .isFalse() } private fun setScreenLock() { lockPatternUtils.setLockCredential( - LockscreenCredential.createPin(PIN), - LockscreenCredential.createNone(), - context.userId + LockscreenCredential.createPin(PIN), + LockscreenCredential.createNone(), + context.userId ) assertWithMessage("Screen Lock should now be set") - .that(lockPatternUtils.isSecure(context.userId)) - .isTrue() + .that(lockPatternUtils.isSecure(context.userId)) + .isTrue() Log.i(TAG, "Device PIN set to $PIN") } @@ -90,14 +95,25 @@ class ScreenLockRule : TestRule { } private fun removeScreenLock() { - lockPatternUtils.setLockCredential( - LockscreenCredential.createNone(), - LockscreenCredential.createPin(PIN), - context.userId - ) - Log.i(TAG, "Device PIN cleared; waiting 50 ms then dismissing Keyguard") - Thread.sleep(50) - windowManager.dismissKeyguard(null, null) + var lockCredentialUnset = lockPatternUtils.setLockCredential( + LockscreenCredential.createNone(), + LockscreenCredential.createPin(PIN), + context.userId) + Thread.sleep(100) + assertWithMessage("Lock screen credential should be unset") + .that(lockCredentialUnset) + .isTrue() + + lockPatternUtils.setLockScreenDisabled(true, context.userId) + Thread.sleep(100) + assertWithMessage("Lockscreen needs to be disabled") + .that(lockPatternUtils.isLockScreenDisabled(context.userId)) + .isTrue() + + // this is here because somehow it helps the keyguard not get stuck + uiDevice.sleep() + Thread.sleep(500) // delay added to avoid initiating camera by double clicking power + uiDevice.wakeUp() } private fun revertLockOnPowerButton() { |