diff options
475 files changed, 10805 insertions, 8686 deletions
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java index 4ad015dcc4e5..c92c6340a6b4 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java @@ -20,6 +20,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import android.app.Activity; import android.content.Context; +import android.os.Bundle; import android.os.RemoteException; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; @@ -153,7 +154,8 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase while (state.keepRunning()) { session.relayout(mWindow, mParams, mWidth, mHeight, mViewVisibility.getAsInt(), mFlags, mOutFrames, - mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls); + mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls, + new Bundle()); } } } 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/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 90ec7000c6d1..528be3ca5e4b 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -4891,13 +4891,15 @@ public class AlarmManagerService extends SystemService { filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); filter.addDataScheme(IntentFilter.SCHEME_PACKAGE); - getContext().registerReceiver(this, filter); + getContext().registerReceiverForAllUsers(this, filter, + /* broadcastPermission */ null, /* scheduler */ null); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); sdFilter.addAction(Intent.ACTION_USER_STOPPED); sdFilter.addAction(Intent.ACTION_UID_REMOVED); - getContext().registerReceiver(this, sdFilter); + getContext().registerReceiverForAllUsers(this, sdFilter, + /* broadcastPermission */ null, /* scheduler */ null); } @Override @@ -4915,9 +4917,6 @@ public class AlarmManagerService extends SystemService { } } return; - case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: - pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); - break; case Intent.ACTION_USER_STOPPED: final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (userHandle >= 0) { @@ -4932,6 +4931,18 @@ public class AlarmManagerService extends SystemService { mRemovalHistory.delete(uid); mLastOpScheduleExactAlarm.delete(uid); return; + case Intent.ACTION_PACKAGE_ADDED: + if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + final String packageUpdated = intent.getData().getSchemeSpecificPart(); + mHandler.obtainMessage( + AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1, + packageUpdated).sendToTarget(); + } + mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES); + return; + case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: + pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); + break; case Intent.ACTION_PACKAGE_REMOVED: if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { // This package is being updated; don't kill its alarms. @@ -4950,15 +4961,6 @@ public class AlarmManagerService extends SystemService { } } break; - case Intent.ACTION_PACKAGE_ADDED: - if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - final String packageUpdated = intent.getData().getSchemeSpecificPart(); - mHandler.obtainMessage( - AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1, - packageUpdated).sendToTarget(); - } - mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES); - return; } if (pkgList != null && (pkgList.length > 0)) { for (String pkg : pkgList) { diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java index a8dd75248dd8..dfa1442a3192 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java @@ -548,7 +548,7 @@ public final class JobStore { out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId())); out.attribute(null, "uid", Integer.toString(jobStatus.getUid())); out.attribute(null, "bias", String.valueOf(jobStatus.getBias())); - out.attribute(null, "priority", String.valueOf(jobStatus.getEffectivePriority())); + out.attribute(null, "priority", String.valueOf(jobStatus.getJob().getPriority())); out.attribute(null, "flags", String.valueOf(jobStatus.getFlags())); if (jobStatus.getInternalFlags() != 0) { out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags())); diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java index dd102bdd726e..e986b1a9bf24 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java @@ -667,8 +667,8 @@ public class AppIdleHistory { long getBucketExpiryTimeMs(String packageName, int userId, int bucket, long elapsedRealtimeMs) { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName, - elapsedRealtimeMs, true); - if (appUsageHistory.bucketExpiryTimesMs == null) { + elapsedRealtimeMs, false /* create */); + if (appUsageHistory == null || appUsageHistory.bucketExpiryTimesMs == null) { return 0; } return appUsageHistory.bucketExpiryTimesMs.get(bucket, 0); diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index 849354bd1d97..4952894c068b 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -78,6 +78,7 @@ import android.content.pm.CrossProfileAppsInternal; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.hardware.display.DisplayManager; import android.net.NetworkScoreManager; @@ -219,7 +220,8 @@ public class AppStandbyController private static final int HEADLESS_APP_CHECK_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS; + | PackageManager.MATCH_DISABLED_COMPONENTS + | PackageManager.MATCH_SYSTEM_ONLY; // To name the lock for stack traces static class Lock {} @@ -253,7 +255,7 @@ public class AppStandbyController private final SparseArray<Set<String>> mActiveAdminApps = new SparseArray<>(); /** - * Set of system apps that are headless (don't have any declared activities, enabled or + * Set of system apps that are headless (don't have any "front door" activities, enabled or * disabled). Presence in this map indicates that the app is a headless system app. */ @GuardedBy("mHeadlessSystemApps") @@ -1573,8 +1575,10 @@ public class AppStandbyController (reason & REASON_MAIN_MASK) == REASON_MAIN_FORCED_BY_SYSTEM; if (app.currentBucket == newBucket && wasForcedBySystem && isForcedBySystem) { - mAppIdleHistory - .noteRestrictionAttempt(packageName, userId, elapsedRealtime, reason); + if (newBucket == STANDBY_BUCKET_RESTRICTED) { + mAppIdleHistory + .noteRestrictionAttempt(packageName, userId, elapsedRealtime, reason); + } // Keep track of all restricting reasons reason = REASON_MAIN_FORCED_BY_SYSTEM | (app.bucketingReason & REASON_SUB_MASK) @@ -1942,7 +1946,7 @@ public class AppStandbyController try { PackageInfo pi = mPackageManager.getPackageInfoAsUser( packageName, HEADLESS_APP_CHECK_FLAGS, userId); - evaluateSystemAppException(pi); + maybeUpdateHeadlessSystemAppCache(pi); } catch (PackageManager.NameNotFoundException e) { synchronized (mHeadlessSystemApps) { mHeadlessSystemApps.remove(packageName); @@ -1950,19 +1954,31 @@ public class AppStandbyController } } - /** Returns true if the exception status changed. */ - private boolean evaluateSystemAppException(@Nullable PackageInfo pkgInfo) { + /** + * Update the "headless system app" cache. + * + * @return true if the cache is updated. + */ + private boolean maybeUpdateHeadlessSystemAppCache(@Nullable PackageInfo pkgInfo) { if (pkgInfo == null || pkgInfo.applicationInfo == null || (!pkgInfo.applicationInfo.isSystemApp() && !pkgInfo.applicationInfo.isUpdatedSystemApp())) { return false; } + final Intent frontDoorActivityIntent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .setPackage(pkgInfo.packageName); + List<ResolveInfo> res = mPackageManager.queryIntentActivitiesAsUser(frontDoorActivityIntent, + HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); + return updateHeadlessSystemAppCache(pkgInfo.packageName, ArrayUtils.isEmpty(res)); + } + + private boolean updateHeadlessSystemAppCache(String packageName, boolean add) { synchronized (mHeadlessSystemApps) { - if (pkgInfo.activities == null || pkgInfo.activities.length == 0) { - // Headless system app. - return mHeadlessSystemApps.add(pkgInfo.packageName); + if (add) { + return mHeadlessSystemApps.add(packageName); } else { - return mHeadlessSystemApps.remove(pkgInfo.packageName); + return mHeadlessSystemApps.remove(packageName); } } } @@ -1999,20 +2015,45 @@ public class AppStandbyController } } + /** Returns the packages that have launcher icons. */ + private Set<String> getSystemPackagesWithLauncherActivities() { + final Intent intent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER); + List<ResolveInfo> activities = mPackageManager.queryIntentActivitiesAsUser(intent, + HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); + final ArraySet<String> ret = new ArraySet<>(); + for (ResolveInfo ri : activities) { + ret.add(ri.activityInfo.packageName); + } + return ret; + } + /** Call on system boot to get the initial set of headless system apps. */ private void loadHeadlessSystemAppCache() { - Slog.d(TAG, "Loading headless system app cache. appIdleEnabled=" + mAppIdleEnabled); + final long start = SystemClock.uptimeMillis(); final List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); + + final Set<String> systemLauncherActivities = getSystemPackagesWithLauncherActivities(); + final int packageCount = packages.size(); for (int i = 0; i < packageCount; i++) { - PackageInfo pkgInfo = packages.get(i); - if (pkgInfo != null && evaluateSystemAppException(pkgInfo)) { + final PackageInfo pkgInfo = packages.get(i); + if (pkgInfo == null) { + continue; + } + final String pkg = pkgInfo.packageName; + final boolean isHeadLess = !systemLauncherActivities.contains(pkg); + + if (updateHeadlessSystemAppCache(pkg, isHeadLess)) { mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, - UserHandle.USER_SYSTEM, -1, pkgInfo.packageName) + UserHandle.USER_SYSTEM, -1, pkg) .sendToTarget(); } } + final long end = SystemClock.uptimeMillis(); + Slog.d(TAG, "Loaded headless system app cache in " + (end - start) + " ms:" + + " appIdleEnabled=" + mAppIdleEnabled); } @Override diff --git a/boot/hiddenapi/hiddenapi-max-target-o.txt b/boot/hiddenapi/hiddenapi-max-target-o.txt index d3b5be906c74..3c16915cf71f 100644 --- a/boot/hiddenapi/hiddenapi-max-target-o.txt +++ b/boot/hiddenapi/hiddenapi-max-target-o.txt @@ -32472,14 +32472,6 @@ Landroid/net/DhcpResults;->setLeaseDuration(I)V Landroid/net/DhcpResults;->setServerAddress(Ljava/lang/String;)Z Landroid/net/DhcpResults;->setVendorInfo(Ljava/lang/String;)V Landroid/net/DhcpResults;->TAG:Ljava/lang/String; -Landroid/net/EthernetManager;-><init>(Landroid/content/Context;Landroid/net/IEthernetManager;)V -Landroid/net/EthernetManager;->mContext:Landroid/content/Context; -Landroid/net/EthernetManager;->mHandler:Landroid/os/Handler; -Landroid/net/EthernetManager;->mListeners:Ljava/util/ArrayList; -Landroid/net/EthernetManager;->mService:Landroid/net/IEthernetManager; -Landroid/net/EthernetManager;->mServiceListener:Landroid/net/IEthernetServiceListener$Stub; -Landroid/net/EthernetManager;->MSG_AVAILABILITY_CHANGED:I -Landroid/net/EthernetManager;->TAG:Ljava/lang/String; Landroid/net/EventLogTags;-><init>()V Landroid/net/EventLogTags;->NTP_FAILURE:I Landroid/net/EventLogTags;->NTP_SUCCESS:I @@ -32513,39 +32505,6 @@ Landroid/net/http/X509TrustManagerExtensions;->mCheckServerTrusted:Ljava/lang/re Landroid/net/http/X509TrustManagerExtensions;->mDelegate:Lcom/android/org/conscrypt/TrustManagerImpl; Landroid/net/http/X509TrustManagerExtensions;->mIsSameTrustConfiguration:Ljava/lang/reflect/Method; Landroid/net/http/X509TrustManagerExtensions;->mTrustManager:Ljavax/net/ssl/X509TrustManager; -Landroid/net/IEthernetManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V -Landroid/net/IEthernetManager$Stub$Proxy;->addListener(Landroid/net/IEthernetServiceListener;)V -Landroid/net/IEthernetManager$Stub$Proxy;->getAvailableInterfaces()[Ljava/lang/String; -Landroid/net/IEthernetManager$Stub$Proxy;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration; -Landroid/net/IEthernetManager$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String; -Landroid/net/IEthernetManager$Stub$Proxy;->isAvailable(Ljava/lang/String;)Z -Landroid/net/IEthernetManager$Stub$Proxy;->mRemote:Landroid/os/IBinder; -Landroid/net/IEthernetManager$Stub$Proxy;->removeListener(Landroid/net/IEthernetServiceListener;)V -Landroid/net/IEthernetManager$Stub$Proxy;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V -Landroid/net/IEthernetManager$Stub;-><init>()V -Landroid/net/IEthernetManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IEthernetManager; -Landroid/net/IEthernetManager$Stub;->DESCRIPTOR:Ljava/lang/String; -Landroid/net/IEthernetManager$Stub;->TRANSACTION_addListener:I -Landroid/net/IEthernetManager$Stub;->TRANSACTION_getAvailableInterfaces:I -Landroid/net/IEthernetManager$Stub;->TRANSACTION_getConfiguration:I -Landroid/net/IEthernetManager$Stub;->TRANSACTION_isAvailable:I -Landroid/net/IEthernetManager$Stub;->TRANSACTION_removeListener:I -Landroid/net/IEthernetManager$Stub;->TRANSACTION_setConfiguration:I -Landroid/net/IEthernetManager;->addListener(Landroid/net/IEthernetServiceListener;)V -Landroid/net/IEthernetManager;->getAvailableInterfaces()[Ljava/lang/String; -Landroid/net/IEthernetManager;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration; -Landroid/net/IEthernetManager;->isAvailable(Ljava/lang/String;)Z -Landroid/net/IEthernetManager;->removeListener(Landroid/net/IEthernetServiceListener;)V -Landroid/net/IEthernetManager;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V -Landroid/net/IEthernetServiceListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V -Landroid/net/IEthernetServiceListener$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String; -Landroid/net/IEthernetServiceListener$Stub$Proxy;->mRemote:Landroid/os/IBinder; -Landroid/net/IEthernetServiceListener$Stub$Proxy;->onAvailabilityChanged(Ljava/lang/String;Z)V -Landroid/net/IEthernetServiceListener$Stub;-><init>()V -Landroid/net/IEthernetServiceListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IEthernetServiceListener; -Landroid/net/IEthernetServiceListener$Stub;->DESCRIPTOR:Ljava/lang/String; -Landroid/net/IEthernetServiceListener$Stub;->TRANSACTION_onAvailabilityChanged:I -Landroid/net/IEthernetServiceListener;->onAvailabilityChanged(Ljava/lang/String;Z)V Landroid/net/IIpConnectivityMetrics$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/net/IIpConnectivityMetrics$Stub$Proxy;->addNetdEventCallback(ILandroid/net/INetdEventCallback;)Z Landroid/net/IIpConnectivityMetrics$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String; diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index 6a685a79cc33..a1575173ded6 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -64,8 +64,6 @@ cc_binary { "libwilhelm", ], - header_libs: ["bionic_libc_platform_headers"], - compile_multilib: "both", cflags: [ diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 815f9455471c..12083b6fe20b 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -15,7 +15,6 @@ #include <android-base/macros.h> #include <binder/IPCThreadState.h> -#include <bionic/pac.h> #include <hwbinder/IPCThreadState.h> #include <utils/Log.h> #include <cutils/memory.h> @@ -183,10 +182,6 @@ int main(int argc, char* const argv[]) ALOGV("app_process main with argv: %s", argv_String.string()); } - // Because of applications that are using PAC instructions incorrectly, PAC - // is disabled in application processes for now. - ScopedDisablePAC x; - AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index c202f6f03b5b..6ef6845c75f2 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -52,6 +52,7 @@ cc_defaults { "-readability-braces-around-statements", "-readability-const-return-type", "-readability-convert-member-functions-to-static", + "-readability-duplicate-include", "-readability-else-after-return", "-readability-identifier-length", "-readability-named-parameter", diff --git a/core/api/current.txt b/core/api/current.txt index a3d3bfc7054d..b5493a3fa8c7 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -142,7 +142,7 @@ package android { field @Deprecated public static final String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE"; field public static final String READ_LOGS = "android.permission.READ_LOGS"; field public static final String READ_MEDIA_AUDIO = "android.permission.READ_MEDIA_AUDIO"; - field public static final String READ_MEDIA_IMAGE = "android.permission.READ_MEDIA_IMAGE"; + field public static final String READ_MEDIA_IMAGES = "android.permission.READ_MEDIA_IMAGES"; field public static final String READ_MEDIA_VIDEO = "android.permission.READ_MEDIA_VIDEO"; field public static final String READ_NEARBY_STREAMING_POLICY = "android.permission.READ_NEARBY_STREAMING_POLICY"; field public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS"; @@ -3336,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(); @@ -3901,6 +3901,7 @@ package android.animation { method public Object getAnimatedValue(String); method public long getCurrentPlayTime(); method public long getDuration(); + method @FloatRange(from=0) public static float getDurationScale(); method public static long getFrameDelay(); method public int getRepeatCount(); method public int getRepeatMode(); @@ -3912,6 +3913,7 @@ package android.animation { method public static android.animation.ValueAnimator ofInt(int...); method public static android.animation.ValueAnimator ofObject(android.animation.TypeEvaluator, java.lang.Object...); method public static android.animation.ValueAnimator ofPropertyValuesHolder(android.animation.PropertyValuesHolder...); + method public static boolean registerDurationScaleChangeListener(@NonNull android.animation.ValueAnimator.DurationScaleChangeListener); method public void removeAllUpdateListeners(); method public void removeUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener); method public void reverse(); @@ -3928,6 +3930,7 @@ package android.animation { method public void setRepeatMode(int); method public void setStartDelay(long); method public void setValues(android.animation.PropertyValuesHolder...); + method public static boolean unregisterDurationScaleChangeListener(@NonNull android.animation.ValueAnimator.DurationScaleChangeListener); field public static final int INFINITE = -1; // 0xffffffff field public static final int RESTART = 1; // 0x1 field public static final int REVERSE = 2; // 0x2 @@ -3937,6 +3940,10 @@ package android.animation { method public void onAnimationUpdate(@NonNull android.animation.ValueAnimator); } + public static interface ValueAnimator.DurationScaleChangeListener { + method public void onChanged(@FloatRange(from=0) float); + } + } package android.annotation { @@ -4276,7 +4283,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); @@ -4286,6 +4292,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); @@ -4296,6 +4303,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); @@ -11292,6 +11300,7 @@ package android.content.pm { method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity); method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle); method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); + method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle); field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED"; } @@ -16399,12 +16408,8 @@ package android.graphics.pdf { package android.graphics.text { public final class LineBreakConfig { - ctor public LineBreakConfig(); method public int getLineBreakStyle(); method public int getLineBreakWordStyle(); - method public void set(@NonNull android.graphics.text.LineBreakConfig); - method public void setLineBreakStyle(int); - method public void setLineBreakWordStyle(int); field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1 field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0 field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2 @@ -16413,6 +16418,13 @@ package android.graphics.text { field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1 } + public static final class LineBreakConfig.Builder { + ctor public LineBreakConfig.Builder(); + method @NonNull public android.graphics.text.LineBreakConfig build(); + method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int); + method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int); + } + public class LineBreaker { method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int); field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2 @@ -17400,7 +17412,7 @@ package android.hardware.camera2 { field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES; - field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SCALER_CROPPING_TYPE; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SCALER_DEFAULT_SECURE_IMAGE_SIZE; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS; @@ -18185,7 +18197,7 @@ package android.hardware.camera2.params { method public int get10BitFormat(); method @NonNull public java.util.List<android.util.Size> getAvailableSizes(); method public int getFormat(); - method public int getStreamUseCase(); + method public long getStreamUseCase(); method public boolean is10BitCapable(); method public boolean isInput(); method public boolean isMaximumSize(); @@ -18243,7 +18255,7 @@ package android.hardware.camera2.params { method public long getDynamicRangeProfile(); method public int getMaxSharedSurfaceCount(); method public int getMirrorMode(); - method public int getStreamUseCase(); + method public long getStreamUseCase(); method @Nullable public android.view.Surface getSurface(); method public int getSurfaceGroupId(); method @NonNull public java.util.List<android.view.Surface> getSurfaces(); @@ -18253,7 +18265,7 @@ package android.hardware.camera2.params { method public void setDynamicRangeProfile(long); method public void setMirrorMode(int); method public void setPhysicalCameraId(@Nullable String); - method public void setStreamUseCase(int); + method public void setStreamUseCase(long); method public void setTimestampBase(int); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR; @@ -18819,6 +18831,7 @@ package android.inputmethodservice { method public void onStartInput(android.view.inputmethod.EditorInfo, boolean); method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean); method public boolean onStartStylusHandwriting(); + method public void onStylusHandwritingMotionEvent(@NonNull android.view.MotionEvent); method public void onUnbindInput(); method @Deprecated public void onUpdateCursor(android.graphics.Rect); method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo); @@ -26064,11 +26077,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 { @@ -26088,7 +26099,7 @@ package android.media.tv.interactive { method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppInfo> getTvInteractiveAppServiceList(); method public void prepare(@NonNull String, int); method public void registerAppLinkInfo(@NonNull String, @NonNull android.media.tv.interactive.AppLinkInfo); - method public void registerCallback(@NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback, @NonNull java.util.concurrent.Executor); + method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback); method public void sendAppLinkCommand(@NonNull String, @NonNull android.os.Bundle); method public void unregisterAppLinkInfo(@NonNull String, @NonNull android.media.tv.interactive.AppLinkInfo); method public void unregisterCallback(@NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback); @@ -26158,10 +26169,10 @@ package android.media.tv.interactive { public abstract static class TvInteractiveAppService.Session implements android.view.KeyEvent.Callback { ctor public TvInteractiveAppService.Session(@NonNull android.content.Context); - method public void layoutSurface(int, int, int, int); - method public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String); - method public void notifySessionStateChanged(int, int); - method public final void notifyTeletextAppStateChanged(int); + method @CallSuper public void layoutSurface(int, int, int, int); + method @CallSuper public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String); + method @CallSuper public void notifySessionStateChanged(int, int); + method @CallSuper public final void notifyTeletextAppStateChanged(int); method public void onAdResponse(@NonNull android.media.tv.AdResponse); method public void onBroadcastInfoResponse(@NonNull android.media.tv.BroadcastInfoResponse); method public void onContentAllowed(); @@ -26195,17 +26206,17 @@ package android.media.tv.interactive { method public void onTuned(@NonNull android.net.Uri); method public void onVideoAvailable(); method public void onVideoUnavailable(int); - method public void removeBroadcastInfo(int); - method public void requestAd(@NonNull android.media.tv.AdRequest); - method public void requestBroadcastInfo(@NonNull android.media.tv.BroadcastInfoRequest); - method public void requestCurrentChannelLcn(); - method public void requestCurrentChannelUri(); - method public void requestCurrentTvInputId(); - method public void requestStreamVolume(); - method public void requestTrackInfoList(); - method public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle); - method public void setMediaViewEnabled(boolean); - method public void setVideoBounds(@NonNull android.graphics.Rect); + method @CallSuper public void removeBroadcastInfo(int); + method @CallSuper public void requestAd(@NonNull android.media.tv.AdRequest); + method @CallSuper public void requestBroadcastInfo(@NonNull android.media.tv.BroadcastInfoRequest); + method @CallSuper public void requestCurrentChannelLcn(); + method @CallSuper public void requestCurrentChannelUri(); + method @CallSuper public void requestCurrentTvInputId(); + method @CallSuper public void requestStreamVolume(); + method @CallSuper public void requestTrackInfoList(); + method @CallSuper public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle); + method @CallSuper public void setMediaViewEnabled(boolean); + method @CallSuper public void setVideoBounds(@NonNull android.graphics.Rect); } public class TvInteractiveAppView extends android.view.ViewGroup { @@ -26508,14 +26519,6 @@ package android.net { method public int getUid(); } - public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { - ctor public EthernetNetworkSpecifier(@NonNull String); - method public int describeContents(); - method @Nullable public String getInterfaceName(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR; - } - public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile { method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms(); method public int getMaxMtu(); @@ -45063,7 +45066,7 @@ package android.text { public static final class PrecomputedText.Params { method public int getBreakStrategy(); method public int getHyphenationFrequency(); - method @Nullable public android.graphics.text.LineBreakConfig getLineBreakConfig(); + method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig(); method @NonNull public android.text.TextDirectionHeuristic getTextDirection(); method @NonNull public android.text.TextPaint getTextPaint(); } @@ -57353,7 +57356,8 @@ package android.widget { method public final android.text.Layout getLayout(); method public float getLetterSpacing(); method public int getLineBounds(int, android.graphics.Rect); - method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig(); + method public int getLineBreakStyle(); + method public int getLineBreakWordStyle(); method public int getLineCount(); method public int getLineHeight(); method public float getLineSpacingExtra(); @@ -57481,7 +57485,8 @@ package android.widget { method public void setKeyListener(android.text.method.KeyListener); method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int); method public void setLetterSpacing(float); - method public void setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig); + method public void setLineBreakStyle(int); + method public void setLineBreakWordStyle(int); method public void setLineHeight(@IntRange(from=0) @Px int); method public void setLineSpacing(float, float); method public void setLines(int); diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 7aef9a6b767a..3d5232ba4f35 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(); + method @RequiresPermission("android.permission.MAKE_UID_VISIBLE") public void makeUidVisible(int, int); 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 } @@ -232,22 +233,6 @@ package android.media.session { package android.net { - public class EthernetManager { - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void addInterfaceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.InterfaceStateListener); - method public void removeInterfaceStateListener(@NonNull android.net.EthernetManager.InterfaceStateListener); - method public void setIncludeTestInterfaces(boolean); - field public static final int ROLE_CLIENT = 1; // 0x1 - field public static final int ROLE_NONE = 0; // 0x0 - field public static final int ROLE_SERVER = 2; // 0x2 - field public static final int STATE_ABSENT = 0; // 0x0 - field public static final int STATE_LINK_DOWN = 1; // 0x1 - field public static final int STATE_LINK_UP = 2; // 0x2 - } - - public static interface EthernetManager.InterfaceStateListener { - method public void onInterfaceStateChanged(@NonNull String, int, int, @Nullable android.net.IpConfiguration); - } - public class LocalSocket implements java.io.Closeable { ctor public LocalSocket(@NonNull java.io.FileDescriptor); } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 37f3cbd84eef..510577b568ba 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -34,6 +34,7 @@ package android { field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"; field public static final String ALLOW_PLACE_IN_MULTI_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS"; + field public static final String ALLOW_SLIPPERY_TOUCHES = "android.permission.ALLOW_SLIPPERY_TOUCHES"; field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER"; field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS"; field public static final String ASSOCIATE_COMPANION_DEVICES = "android.permission.ASSOCIATE_COMPANION_DEVICES"; @@ -243,6 +244,7 @@ package android { field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES"; field public static final String READ_CARRIER_APP_INFO = "android.permission.READ_CARRIER_APP_INFO"; field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; + field public static final String READ_CLIPBOARD_IN_BACKGROUND = "android.permission.READ_CLIPBOARD_IN_BACKGROUND"; field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS"; field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG"; field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE"; @@ -469,7 +471,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); @@ -1128,7 +1129,7 @@ package android.app.admin { field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE = "android.app.action.ROLE_HOLDER_PROVISION_MANAGED_PROFILE"; field public static final String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER"; field @Deprecated public static final String ACTION_STATE_USER_SETUP_COMPLETE = "android.app.action.STATE_USER_SETUP_COMPLETE"; - field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER"; + field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER"; field public static final String EXTRA_FORCE_UPDATE_ROLE_HOLDER = "android.app.extra.FORCE_UPDATE_ROLE_HOLDER"; field public static final String EXTRA_LOST_MODE_LOCATION = "android.app.extra.LOST_MODE_LOCATION"; field public static final String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME"; @@ -1161,8 +1162,8 @@ package android.app.admin { field public static final String REQUIRED_APP_MANAGED_PROFILE = "android.app.REQUIRED_APP_MANAGED_PROFILE"; field public static final String REQUIRED_APP_MANAGED_USER = "android.app.REQUIRED_APP_MANAGED_USER"; field public static final int RESULT_DEVICE_OWNER_SET = 123; // 0x7b - field public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; // 0x1 - field public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; // 0x2 + field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; // 0x1 + field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; // 0x2 field public static final int RESULT_UPDATE_ROLE_HOLDER = 2; // 0x2 field public static final int RESULT_WORK_PROFILE_CREATED = 122; // 0x7a field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4 @@ -1701,8 +1702,10 @@ package android.app.cloudsearch { method @NonNull public String getTitle(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.cloudsearch.SearchResult> CREATOR; + field public static final String EXTRAINFO_ACTION_APP_CARD = "android.app.cloudsearch.ACTION_APP_CARD"; 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_ACTION_INSTALL_BUTTON = "android.app.cloudsearch.ACTION_INSTALL_BUTTON"; field public static final String EXTRAINFO_APP_BADGES = "android.app.cloudsearch.APP_BADGES"; 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"; @@ -1710,6 +1713,8 @@ package android.app.cloudsearch { field public static final String EXTRAINFO_APP_DOMAIN_URL = "android.app.cloudsearch.APP_DOMAIN_URL"; field public static final String EXTRAINFO_APP_IARC = "android.app.cloudsearch.APP_IARC"; field public static final String EXTRAINFO_APP_ICON = "android.app.cloudsearch.APP_ICON"; + field public static final String EXTRAINFO_APP_INSTALL_COUNT = "android.app.cloudsearch.APP_INSTALL_COUNT"; + field public static final String EXTRAINFO_APP_PACKAGE_NAME = "android.app.cloudsearch.APP_PACKAGE_NAME"; 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"; @@ -2948,6 +2953,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"; @@ -3187,6 +3193,7 @@ package android.content.pm { } public class CrossProfileApps { + method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle); method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); } @@ -6946,7 +6953,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[]); @@ -8521,45 +8528,6 @@ package android.metrics { package android.net { - public class EthernetManager { - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>); - method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>); - } - - public static interface EthernetManager.TetheredInterfaceCallback { - method public void onAvailable(@NonNull String); - method public void onUnavailable(); - } - - public static class EthernetManager.TetheredInterfaceRequest { - method public void release(); - } - - public final class EthernetNetworkManagementException extends java.lang.RuntimeException implements android.os.Parcelable { - ctor public EthernetNetworkManagementException(@NonNull String); - method public int describeContents(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkManagementException> CREATOR; - } - - public final class EthernetNetworkUpdateRequest implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public android.net.IpConfiguration getIpConfiguration(); - method @Nullable public android.net.NetworkCapabilities getNetworkCapabilities(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR; - } - - public static final class EthernetNetworkUpdateRequest.Builder { - ctor public EthernetNetworkUpdateRequest.Builder(); - ctor public EthernetNetworkUpdateRequest.Builder(@NonNull android.net.EthernetNetworkUpdateRequest); - method @NonNull public android.net.EthernetNetworkUpdateRequest build(); - method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setIpConfiguration(@NonNull android.net.IpConfiguration); - method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setNetworkCapabilities(@Nullable android.net.NetworkCapabilities); - } - public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { ctor public MatchAllNetworkSpecifier(); method public int describeContents(); @@ -9030,7 +8998,7 @@ package android.net.wifi.nl80211 { method public void enableVerboseLogging(boolean); method @NonNull public int[] getChannelsMhzForBand(int); method @Nullable public android.net.wifi.nl80211.DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String); - method public int getMaxNumScanSsids(@NonNull String); + method public int getMaxSsidsPerScan(@NonNull String); method @NonNull public java.util.List<android.net.wifi.nl80211.NativeScanResult> getScanResults(@NonNull String, int); method @Nullable public android.net.wifi.nl80211.WifiNl80211Manager.TxPacketCounters getTxPacketCounters(@NonNull String); method public void notifyCountryCodeChanged(@Nullable String); @@ -9820,11 +9788,12 @@ 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(); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser(); + method public static boolean isRemoveResultSuccessful(int); method public boolean isRestrictedProfile(); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle); @@ -9842,7 +9811,10 @@ package android.os { field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background"; field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2 field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1 - field public static final int REMOVE_RESULT_ERROR = 3; // 0x3 + field public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; // 0xfffffffc + field public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; // 0xffffffff + field public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; // 0xfffffffd + field public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2; // 0xfffffffe field public static final int REMOVE_RESULT_REMOVED = 0; // 0x0 field public static final int RESTRICTION_NOT_SET = 0; // 0x0 field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2 @@ -10332,6 +10304,7 @@ package android.provider { field public static final String NAMESPACE_MEDIA_NATIVE = "media_native"; field public static final String NAMESPACE_NETD_NATIVE = "netd_native"; field public static final String NAMESPACE_NNAPI_NATIVE = "nnapi_native"; + field public static final String NAMESPACE_ON_DEVICE_PERSONALIZATION = "on_device_personalization"; field public static final String NAMESPACE_OTA = "ota"; field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; field public static final String NAMESPACE_PERMISSIONS = "permissions"; @@ -10892,10 +10865,11 @@ package android.service.ambientcontext { } public static final class AmbientContextDetectionResult.Builder { - ctor public AmbientContextDetectionResult.Builder(); + ctor public AmbientContextDetectionResult.Builder(@NonNull String); method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder addEvent(@NonNull android.app.ambientcontext.AmbientContextEvent); + method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder addEvents(@NonNull java.util.List<android.app.ambientcontext.AmbientContextEvent>); method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult build(); - method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder setPackageName(@NonNull String); + method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder clearEvents(); } public abstract class AmbientContextDetectionService extends android.app.Service { @@ -10916,9 +10890,8 @@ package android.service.ambientcontext { } public static final class AmbientContextDetectionServiceStatus.Builder { - ctor public AmbientContextDetectionServiceStatus.Builder(); + ctor public AmbientContextDetectionServiceStatus.Builder(@NonNull String); method @NonNull public android.service.ambientcontext.AmbientContextDetectionServiceStatus build(); - method @NonNull public android.service.ambientcontext.AmbientContextDetectionServiceStatus.Builder setPackageName(@NonNull String); method @NonNull public android.service.ambientcontext.AmbientContextDetectionServiceStatus.Builder setStatusCode(int); } @@ -13374,7 +13347,7 @@ package android.telephony { } public class TelephonyManager { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener); + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener); method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback); method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String); @@ -13474,7 +13447,8 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled(); method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback); + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>); @@ -13524,6 +13498,7 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterCarrierPrivilegesCallback(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback); method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor); method public void updateServiceLocation(); field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED"; @@ -13629,8 +13604,13 @@ package android.telephony { field public static final int RESULT_SUCCESS = 0; // 0x0 } - public static interface TelephonyManager.CarrierPrivilegesListener { - method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]); + public static interface TelephonyManager.CarrierPrivilegesCallback { + method public void onCarrierPrivilegesChanged(@NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.Integer>); + method public default void onCarrierServiceChanged(@Nullable String, int); + } + + @Deprecated public static interface TelephonyManager.CarrierPrivilegesListener { + method @Deprecated public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]); } public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 5aec193f33d4..db95a1feec91 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -19,6 +19,7 @@ package android { field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final String INSTALL_TEST_ONLY_PACKAGE = "android.permission.INSTALL_TEST_ONLY_PACKAGE"; field public static final String KEEP_UNINSTALLED_PACKAGES = "android.permission.KEEP_UNINSTALLED_PACKAGES"; + field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE"; field @Deprecated public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; field public static final String MANAGE_ACTIVITY_TASKS = "android.permission.MANAGE_ACTIVITY_TASKS"; field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES"; @@ -95,8 +96,7 @@ package android.accessibilityservice { package android.animation { public class ValueAnimator extends android.animation.Animator { - method public static float getDurationScale(); - method public static void setDurationScale(float); + method @MainThread public static void setDurationScale(@FloatRange(from=0) float); } } @@ -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 { @@ -836,6 +836,7 @@ package android.content.pm { method @Nullable public String getSystemTextClassifierPackageName(); method @Nullable public String getWellbeingPackageName(); method public void holdLock(android.os.IBinder, int); + method @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE) public void makeUidVisible(int, int); method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>); field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; field public static final String FEATURE_COMMUNAL_MODE = "android.software.communal_mode"; 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/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 06b424bcb417..6ab7ae6d0cee 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -17,7 +17,9 @@ package android.animation; import android.annotation.CallSuper; +import android.annotation.FloatRange; import android.annotation.IntDef; +import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; @@ -35,8 +37,10 @@ import android.view.animation.LinearInterpolator; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * This class provides a simple timing engine for running animations @@ -91,6 +95,9 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static float sDurationScale = 1.0f; + private static final ArrayList<WeakReference<DurationScaleChangeListener>> + sDurationScaleChangeListeners = new ArrayList<>(); + /** * Internal variables * NOTE: This object implements the clone() method, making a deep copy of any referenced @@ -308,20 +315,92 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio */ @UnsupportedAppUsage @TestApi - public static void setDurationScale(float durationScale) { + @MainThread + public static void setDurationScale(@FloatRange(from = 0) float durationScale) { sDurationScale = durationScale; + List<WeakReference<DurationScaleChangeListener>> listenerCopy; + + synchronized (sDurationScaleChangeListeners) { + listenerCopy = new ArrayList<>(sDurationScaleChangeListeners); + } + + for (WeakReference<DurationScaleChangeListener> listenerRef : listenerCopy) { + final DurationScaleChangeListener listener = listenerRef.get(); + if (listener != null) { + listener.onChanged(durationScale); + } + } } /** - * @hide + * Returns the system-wide scaling factor for Animator-based animations. + * + * This affects both the start delay and duration of all such animations. Setting to 0 will + * cause animations to end immediately. The default value is 1.0f. + * + * @return the duration scale. */ - @UnsupportedAppUsage - @TestApi + @FloatRange(from = 0) public static float getDurationScale() { return sDurationScale; } /** + * Registers a {@link DurationScaleChangeListener} + * + * This listens for changes to the system-wide scaling factor for Animator-based animations. + * Listeners will be called on the main thread. + * + * @param listener the listener to register. + * @return true if the listener was registered. + */ + public static boolean registerDurationScaleChangeListener( + @NonNull DurationScaleChangeListener listener) { + int posToReplace = -1; + synchronized (sDurationScaleChangeListeners) { + for (int i = 0; i < sDurationScaleChangeListeners.size(); i++) { + final WeakReference<DurationScaleChangeListener> ref = + sDurationScaleChangeListeners.get(i); + if (ref.get() == null) { + if (posToReplace == -1) { + posToReplace = i; + } + } else if (ref.get() == listener) { + return false; + } + } + if (posToReplace != -1) { + sDurationScaleChangeListeners.set(posToReplace, new WeakReference<>(listener)); + return true; + } else { + return sDurationScaleChangeListeners.add(new WeakReference<>(listener)); + } + } + } + + /** + * Unregisters a DurationScaleChangeListener. + * + * @see #registerDurationScaleChangeListener(DurationScaleChangeListener) + * @param listener the listener to unregister. + * @return true if the listener was unregistered. + */ + public static boolean unregisterDurationScaleChangeListener( + @NonNull DurationScaleChangeListener listener) { + synchronized (sDurationScaleChangeListeners) { + WeakReference<DurationScaleChangeListener> listenerRefToRemove = null; + for (WeakReference<DurationScaleChangeListener> listenerRef : + sDurationScaleChangeListeners) { + if (listenerRef.get() == listener) { + listenerRefToRemove = listenerRef; + break; + } + } + return sDurationScaleChangeListeners.remove(listenerRefToRemove); + } + } + + /** * Returns whether animators are currently enabled, system-wide. By default, all * animators are enabled. This can change if either the user sets a Developer Option * to set the animator duration scale to 0 or by Battery Savery mode being enabled @@ -1709,4 +1788,18 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio public void setAnimationHandler(@Nullable AnimationHandler animationHandler) { mAnimationHandler = animationHandler; } + + /** + * Listener interface for the system-wide scaling factor for Animator-based animations. + * + * @see #registerDurationScaleChangeListener(DurationScaleChangeListener) + * @see #unregisterDurationScaleChangeListener(DurationScaleChangeListener) + */ + public interface DurationScaleChangeListener { + /** + * Called when the duration scale changes. + * @param scale the duration scale + */ + void onChanged(@FloatRange(from = 0) float scale); + } } 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..3d0ed20b60c6 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -868,6 +868,7 @@ public final class ActivityThread extends ClientTransactionHandler String processName; @UnsupportedAppUsage ApplicationInfo appInfo; + String sdkSandboxClientAppPackage; @UnsupportedAppUsage List<ProviderInfo> providers; ComponentName instrumentationName; @@ -1113,9 +1114,9 @@ public final class ActivityThread extends ClientTransactionHandler @Override public final void bindApplication(String processName, ApplicationInfo appInfo, - ProviderInfoList providerList, ComponentName instrumentationName, - ProfilerInfo profilerInfo, Bundle instrumentationArgs, - IInstrumentationWatcher instrumentationWatcher, + String sdkSandboxClientAppPackage, ProviderInfoList providerList, + ComponentName instrumentationName, ProfilerInfo profilerInfo, + Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, @@ -1155,6 +1156,7 @@ public final class ActivityThread extends ClientTransactionHandler AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; + data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage; data.providers = providerList.getList(); data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; @@ -3587,7 +3589,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 +4288,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 +4477,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) { @@ -6536,6 +6538,9 @@ public final class ActivityThread extends ClientTransactionHandler } data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); + if (data.sdkSandboxClientAppPackage != null) { + data.info.setSdkSandboxStorage(data.sdkSandboxClientAppPackage); + } if (agent != null) { handleAttachAgent(agent, data.info); @@ -6695,7 +6700,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 +7570,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/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 7c7c7ef382c1..4829dc085bd9 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -2367,7 +2367,7 @@ public class AppOpsManager { null, // no permission for OP_WRITE_MEDIA_AUDIO Manifest.permission.READ_MEDIA_VIDEO, null, // no permission for OP_WRITE_MEDIA_VIDEO - Manifest.permission.READ_MEDIA_IMAGE, + Manifest.permission.READ_MEDIA_IMAGES, null, // no permission for OP_WRITE_MEDIA_IMAGES null, // no permission for OP_LEGACY_STORAGE null, // no permission for OP_ACCESS_ACCESSIBILITY diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index dca5c542af17..7ffa61be7604 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -3832,4 +3832,13 @@ public class ApplicationPackageManager extends PackageManager { throw re.rethrowAsRuntimeException(); } } + + @Override + public void makeUidVisible(int recipientUid, int visibleUid) { + try { + mPM.makeUidVisible(recipientUid, visibleUid); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index a3dd705a7e29..f5eb1f6e24ed 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1998,7 +1998,7 @@ class ContextImpl extends Context { private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) { // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser and - // ActivityManagerLocal.bindSupplementalProcessService + // ActivityManagerLocal.bindSdkSandboxService IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); 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/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 77657d58cc4c..f4fbcceeab8f 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -72,6 +72,7 @@ oneway interface IApplicationThread { @UnsupportedAppUsage void scheduleStopService(IBinder token); void bindApplication(in String packageName, in ApplicationInfo info, + in String sdkSandboxClientAppPackage, in ProviderInfoList providerList, in ComponentName testName, in ProfilerInfo profilerInfo, in Bundle testArguments, IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index cf259e577a5a..deefea83c13d 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -37,6 +37,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.os.FileUtils; import android.os.GraphicsEnvironment; import android.os.Handler; @@ -411,6 +412,26 @@ public final class LoadedApk { } } + /** @hide */ + void setSdkSandboxStorage(String sdkSandboxClientAppPackage) { + int userId = UserHandle.myUserId(); + mDeviceProtectedDataDirFile = Environment + .getDataMiscDeSharedSdkSandboxDirectory(userId, sdkSandboxClientAppPackage) + .getAbsoluteFile(); + mCredentialProtectedDataDirFile = Environment + .getDataMiscCeSharedSdkSandboxDirectory(userId, sdkSandboxClientAppPackage) + .getAbsoluteFile(); + + if ((mApplicationInfo.privateFlags + & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0 + && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { + mDataDirFile = mDeviceProtectedDataDirFile; + } else { + mDataDirFile = mCredentialProtectedDataDirFile; + } + mDataDir = mDataDirFile.getAbsolutePath(); + } + public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo, List<String> outZipPaths) { @@ -1352,9 +1373,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 +1406,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 +1465,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/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index c6e36a36701b..150888ccb2d8 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -24,6 +24,9 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; @@ -39,6 +42,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Pair; import android.util.Slog; import android.view.View; @@ -520,6 +524,27 @@ public class StatusBarManager { private final Map<NearbyMediaDevicesProvider, NearbyMediaDevicesProviderWrapper> nearbyMediaDevicesProviderMap = new HashMap<>(); + /** + * Media controls based on {@link android.app.Notification.MediaStyle} notifications will have + * actions based on the media session's {@link android.media.session.PlaybackState}, rather than + * the notification's actions. + * + * These actions will be: + * - Play/Pause (depending on whether the current state is a playing state) + * - Previous (if declared), or a custom action if the slot is not reserved with + * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV} + * - Next (if declared), or a custom action if the slot is not reserved with + * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT} + * - Custom action + * - Custom action + * + * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV + * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT + */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) + private static final long MEDIA_CONTROL_SESSION_ACTIONS = 203800354L; + @UnsupportedAppUsage private Context mContext; private IStatusBarService mService; @@ -844,6 +869,24 @@ public class StatusBarManager { } /** + * Sets an active {@link android.service.quicksettings.TileService} to listening state + * + * The {@code componentName}'s package must match the calling package. + * + * @param componentName the tile to set into listening state + * @see android.service.quicksettings.TileService#requestListeningState + * @hide + */ + public void requestTileServiceListeningState(@NonNull ComponentName componentName) { + Objects.requireNonNull(componentName); + try { + getService().requestTileServiceListeningState(componentName, mContext.getUserId()); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** * Request to the user to add a {@link android.service.quicksettings.TileService} * to the set of current QS tiles. * <p> @@ -1109,6 +1152,20 @@ public class StatusBarManager { } } + /** + * Checks whether the given package should use session-based actions for its media controls. + * + * @param packageName App posting media controls + * @param userId Current user ID + * @return true if the app supports session actions + * + * @hide + */ + public static boolean useMediaSessionActionsForApp(String packageName, int userId) { + UserHandle handle = UserHandle.getUserHandleForUid(userId); + return CompatChanges.isChangeEnabled(MEDIA_CONTROL_SESSION_ACTIONS, packageName, handle); + } + /** @hide */ public static String windowStateToString(int state) { if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 58db93c123bb..6615374f71ec 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -138,8 +138,6 @@ import android.media.tv.tunerresourcemanager.TunerResourceManager; import android.nearby.NearbyFrameworkInitializer; import android.net.ConnectivityFrameworkInitializer; import android.net.ConnectivityFrameworkInitializerTiramisu; -import android.net.EthernetManager; -import android.net.IEthernetManager; import android.net.INetworkPolicyManager; import android.net.IPacProxyManager; import android.net.IVpnManager; @@ -156,6 +154,7 @@ import android.net.vcn.VcnManager; import android.net.wifi.WifiFrameworkInitializer; import android.net.wifi.nl80211.WifiNl80211Manager; import android.nfc.NfcManager; +import android.ondevicepersonalization.OnDevicePersonalizationFrameworkInitializer; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStatsManager; @@ -789,15 +788,6 @@ public final class SystemServiceRegistry { return new LowpanManager(ctx.getOuterContext(), service); }}); - registerService(Context.ETHERNET_SERVICE, EthernetManager.class, - new CachedServiceFetcher<EthernetManager>() { - @Override - public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder b = ServiceManager.getServiceOrThrow(Context.ETHERNET_SERVICE); - IEthernetManager service = IEthernetManager.Stub.asInterface(b); - return new EthernetManager(ctx.getOuterContext(), service); - }}); - registerService(Context.WIFI_NL80211_SERVICE, WifiNl80211Manager.class, new CachedServiceFetcher<WifiNl80211Manager>() { @Override @@ -1571,6 +1561,7 @@ public final class SystemServiceRegistry { SafetyCenterFrameworkInitializer.registerServiceWrappers(); ConnectivityFrameworkInitializerTiramisu.registerServiceWrappers(); NearbyFrameworkInitializer.registerServiceWrappers(); + OnDevicePersonalizationFrameworkInitializer.registerServiceWrappers(); } finally { // If any of the above code throws, we're in a pretty bad shape and the process // will likely crash, but we'll reset it just in case there's an exception handler... 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/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4c7b91056ca1..27fe312706ff 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -719,10 +719,11 @@ public class DevicePolicyManager { /** * A {@code boolean} extra which determines whether to force a role holder update, regardless - * of any internal conditions {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER} might have. + * of any internal conditions {@link #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} might + * have. * * <p>This extra can be provided to intents with action {@link - * #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}. + * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER}. * * @hide */ @@ -3281,39 +3282,43 @@ public class DevicePolicyManager { * * <p>The activity must handle the device policy management role holder update and set the * intent result to either {@link Activity#RESULT_OK} if the update was successful, {@link - * #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it encounters a problem - * that may be solved by relaunching it again, or {@link - * #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if it encounters a problem - * that will not be solved by relaunching it again. + * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it encounters a + * problem that may be solved by relaunching it again, or {@link + * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if it encounters a + * problem that will not be solved by relaunching it again. * * <p>If this activity has additional internal conditions which are not met, it should return - * {@link #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR}. + * {@link #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR}. * * @hide */ @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @SystemApi - public static final String ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER = - "android.app.action.UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER"; + public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER = + "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER"; /** - * Result code that can be returned by the {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER} - * handler if it encounters a problem that may be solved by relaunching it again. + * Result code that can be returned by the {@link + * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if it encounters a problem + * that may be solved by relaunching it again. * * @hide */ @SystemApi - public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; + public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = + 1; /** - * Result code that can be returned by the {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER} - * handler if it encounters a problem that will not be solved by relaunching it again. + * Result code that can be returned by the {@link + * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if it encounters a problem that + * will not be solved by relaunching it again. * * @hide */ @SystemApi - public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; + public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = + 2; /** * An {@link Intent} extra which resolves to a custom user consent screen. diff --git a/core/java/android/app/cloudsearch/SearchResult.java b/core/java/android/app/cloudsearch/SearchResult.java index af8adacd4258..c6583b65f9c2 100644 --- a/core/java/android/app/cloudsearch/SearchResult.java +++ b/core/java/android/app/cloudsearch/SearchResult.java @@ -71,6 +71,10 @@ public final class SearchResult implements Parcelable { EXTRAINFO_APP_BADGES, EXTRAINFO_ACTION_BUTTON_TEXT_PREREGISTERING, EXTRAINFO_ACTION_BUTTON_IMAGE_PREREGISTERING, + EXTRAINFO_ACTION_APP_CARD, + EXTRAINFO_ACTION_INSTALL_BUTTON, + EXTRAINFO_APP_PACKAGE_NAME, + EXTRAINFO_APP_INSTALL_COUNT, EXTRAINFO_WEB_URL, EXTRAINFO_WEB_ICON}) public @interface SearchResultExtraInfoKey {} @@ -119,6 +123,20 @@ 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_ACTION_APP_CARD = + "android.app.cloudsearch.ACTION_APP_CARD"; + /** Intent for tapping the install button, PendingIntent expected. */ + @SuppressLint("IntentName") + public static final String EXTRAINFO_ACTION_INSTALL_BUTTON = + "android.app.cloudsearch.ACTION_INSTALL_BUTTON"; + /** App's package name, String value expected. */ + public static final String EXTRAINFO_APP_PACKAGE_NAME = + "android.app.cloudsearch.APP_PACKAGE_NAME"; + /** App's install count, double value expected. */ + public static final String EXTRAINFO_APP_INSTALL_COUNT = + "android.app.cloudsearch.APP_INSTALL_COUNT"; /** 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/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/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java index 94f056110bf7..b6917e269916 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -104,7 +104,44 @@ public class CrossProfileApps { mContext.getAttributionTag(), component, targetUser.getIdentifier(), - true); + true, + null, + null); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** + * Starts the specified main activity of the caller package in the specified profile, launching + * in the specified activity. + * + * @param component The ComponentName of the activity to launch, it must be exported and has + * action {@link android.content.Intent#ACTION_MAIN}, category + * {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will + * be thrown. + * @param targetUser The UserHandle of the profile, must be one of the users returned by + * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will + * be thrown. + * @param callingActivity The activity to start the new activity from for the purposes of + * deciding which task the new activity should belong to. If {@code null}, the activity + * will always be started in a new task. + * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}. + */ + public void startMainActivity(@NonNull ComponentName component, + @NonNull UserHandle targetUser, + @Nullable Activity callingActivity, + @Nullable Bundle options) { + try { + mService.startActivityAsUser( + mContext.getIApplicationThread(), + mContext.getPackageName(), + mContext.getAttributionTag(), + component, + targetUser.getIdentifier(), + true, + callingActivity != null ? callingActivity.getActivityToken() : null, + options); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } @@ -191,6 +228,48 @@ public class CrossProfileApps { * @param targetUser The UserHandle of the profile, must be one of the users returned by * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will * be thrown. + * @param callingActivity The activity to start the new activity from for the purposes of + * deciding which task the new activity should belong to. If {@code null}, the activity + * will always be started in a new task. + * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.INTERACT_ACROSS_PROFILES, + android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) + public void startActivity( + @NonNull ComponentName component, + @NonNull UserHandle targetUser, + @Nullable Activity callingActivity, + @Nullable Bundle options) { + try { + mService.startActivityAsUser( + mContext.getIApplicationThread(), + mContext.getPackageName(), + mContext.getAttributionTag(), + component, + targetUser.getIdentifier(), + false, + callingActivity != null ? callingActivity.getActivityToken() : null, + options); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** + * Starts the specified activity of the caller package in the specified profile. Unlike + * {@link #startMainActivity}, this can start any activity of the caller package, not just + * the main activity. + * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} + * or {@link android.Manifest.permission#START_CROSS_PROFILE_ACTIVITIES} + * permission and both the caller and target user profiles must be in the same profile group. + * + * @param component The ComponentName of the activity to launch. It must be exported. + * @param targetUser The UserHandle of the profile, must be one of the users returned by + * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will + * be thrown. * @hide */ @SystemApi @@ -201,7 +280,7 @@ public class CrossProfileApps { try { mService.startActivityAsUser(mContext.getIApplicationThread(), mContext.getPackageName(), mContext.getAttributionTag(), component, - targetUser.getIdentifier(), false); + targetUser.getIdentifier(), false, null, null); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl index e2850f111c4f..4f2c1069275e 100644 --- a/core/java/android/content/pm/ICrossProfileApps.aidl +++ b/core/java/android/content/pm/ICrossProfileApps.aidl @@ -29,7 +29,7 @@ import android.os.UserHandle; interface ICrossProfileApps { void startActivityAsUser(in IApplicationThread caller, in String callingPackage, in String callingFeatureId, in ComponentName component, int userId, - boolean launchMainActivity); + boolean launchMainActivity, in IBinder task, in Bundle options); void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage, in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity, in Bundle options); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 0f236dfe1a8b..ca7d77b2c44a 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -781,7 +781,11 @@ interface IPackageManager { boolean isAutoRevokeWhitelisted(String packageName); - void grantImplicitAccess(int queryingUid, String visibleAuthority); + void makeProviderVisible(int recipientAppId, String visibleAuthority); + + @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + + ".permission.MAKE_UID_VISIBLE)") + void makeUidVisible(int recipientAppId, int visibleUid); IBinder getHoldLockToken(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index f9beaa7cd0e9..81c941eedef0 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -10281,19 +10281,38 @@ public abstract class PackageManager { } /** - * Grants implicit visibility of the package that provides an authority to a querying UID. + * Makes a package that provides an authority {@code visibleAuthority} become visible to the + * application {@code recipientUid}. * * @throws SecurityException when called by a package other than the contacts provider * @hide */ - public void grantImplicitAccess(int queryingUid, String visibleAuthority) { + public void makeProviderVisible(int recipientUid, String visibleAuthority) { try { - ActivityThread.getPackageManager().grantImplicitAccess(queryingUid, visibleAuthority); + ActivityThread.getPackageManager().makeProviderVisible(recipientUid, visibleAuthority); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** + * Makes the package associated with the uid {@code visibleUid} become visible to the + * recipient uid application. + * + * @param recipientUid The uid of the application that is being given access to {@code + * visibleUid} + * @param visibleUid The uid of the application that is becoming accessible to {@code + * recipientAppId} + * @hide + */ + @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE) + @TestApi + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void makeUidVisible(int recipientUid, int visibleUid) { + throw new UnsupportedOperationException( + "makeUidVisible not implemented in subclass"); + } + // Some of the flags don't affect the query result, but let's be conservative and cache // each combination of flags separately. diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java index 3f5c5d21428e..d94b0d8f9072 100644 --- a/core/java/android/content/pm/Signature.java +++ b/core/java/android/content/pm/Signature.java @@ -312,7 +312,7 @@ public class Signature implements Parcelable { * @hide */ public static boolean areExactMatch(Signature[] a, Signature[] b) { - return (a.length == b.length) && ArrayUtils.containsAll(a, b) + return (ArrayUtils.size(a) == ArrayUtils.size(b)) && ArrayUtils.containsAll(a, b) && ArrayUtils.containsAll(b, a); } @@ -387,4 +387,4 @@ public class Signature implements Parcelable { return sPrime; } -}
\ No newline at end of file +} diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java index 8b86a16075e9..a65b6815f8ad 100644 --- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java @@ -379,6 +379,30 @@ public class FrameworkParsingPackageUtils { } /** + * Computes the maxSdkVersion. If the package is not compatible with this platform, populates + * {@code outError[0]} with an error message. + * <p> + * {@code maxVers} is compared against {@code platformSdkVersion}. If {@code maxVers} is less + * than the {@code platformSdkVersion} then populates {@code outError[0]} with an error message. + * Otherwise, it returns {@code maxVers} unmodified. + * + * @param maxVers maxSdkVersion number, if specified in the application manifest, or {@code + * Integer.MAX_VALUE} otherwise + * @param platformSdkVersion platform SDK version number, typically Build.VERSION.SDK_INT + * @return the maxSdkVersion that was recognised or an error if the condition is not satisfied + */ + public static ParseResult<Integer> computeMaxSdkVersion(@IntRange(from = 0) int maxVers, + @IntRange(from = 1) int platformSdkVersion, @NonNull ParseInput input) { + if (platformSdkVersion > maxVers) { + return input.error(PackageManager.INSTALL_FAILED_NEWER_SDK, + "Requires max SDK version " + maxVers + " but is " + + platformSdkVersion); + } else { + return input.success(maxVers); + } + } + + /** * Matches a given {@code targetCode} against a set of release codeNames. Target codes can * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form {@code * [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}). diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java index 7b24cc4836d0..3952467324fe 100644 --- a/core/java/android/hardware/CameraStreamStats.java +++ b/core/java/android/hardware/CameraStreamStats.java @@ -49,7 +49,7 @@ public class CameraStreamStats implements Parcelable { private float[] mHistogramBins; private long[] mHistogramCounts; private long mDynamicRangeProfile; - private int mStreamUseCase; + private long mStreamUseCase; private static final String TAG = "CameraStreamStats"; @@ -73,7 +73,7 @@ public class CameraStreamStats implements Parcelable { public CameraStreamStats(int width, int height, int format, float maxPreviewFps, int dataSpace, long usage, long requestCount, long errorCount, int startLatencyMs, int maxHalBuffers, int maxAppBuffers, long dynamicRangeProfile, - int streamUseCase) { + long streamUseCase) { mWidth = width; mHeight = height; mFormat = format; @@ -135,7 +135,7 @@ public class CameraStreamStats implements Parcelable { dest.writeFloatArray(mHistogramBins); dest.writeLongArray(mHistogramCounts); dest.writeLong(mDynamicRangeProfile); - dest.writeInt(mStreamUseCase); + dest.writeLong(mStreamUseCase); } public void readFromParcel(Parcel in) { @@ -154,7 +154,7 @@ public class CameraStreamStats implements Parcelable { mHistogramBins = in.createFloatArray(); mHistogramCounts = in.createLongArray(); mDynamicRangeProfile = in.readLong(); - mStreamUseCase = in.readInt(); + mStreamUseCase = in.readLong(); } public int getWidth() { @@ -217,7 +217,7 @@ public class CameraStreamStats implements Parcelable { return mDynamicRangeProfile; } - public int getStreamUseCase() { + public long getStreamUseCase() { return mStreamUseCase; } } diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 7bebe1ff14c3..b05e6d131957 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -3563,8 +3563,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri */ @PublicKey @NonNull - public static final Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES = - new Key<int[]>("android.scaler.availableStreamUseCases", int[].class); + public static final Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES = + new Key<long[]>("android.scaler.availableStreamUseCases", long[].class); /** * <p>An array of mandatory stream combinations with stream use cases. diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java index 465abfb55540..a3bc66546a6a 100644 --- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java +++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java @@ -66,7 +66,7 @@ public final class MandatoryStreamCombination { private final boolean mIsUltraHighResolution; private final boolean mIsMaximumSize; private final boolean mIs10BitCapable; - private final int mStreamUseCase; + private final long mStreamUseCase; /** * Create a new {@link MandatoryStreamInformation}. @@ -168,7 +168,7 @@ public final class MandatoryStreamCombination { */ public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format, boolean isMaximumSize, boolean isInput, boolean isUltraHighResolution, - boolean is10BitCapable, @StreamUseCase int streamUseCase) { + boolean is10BitCapable, @StreamUseCase long streamUseCase) { if (availableSizes.isEmpty()) { throw new IllegalArgumentException("No available sizes"); } @@ -308,9 +308,9 @@ public final class MandatoryStreamCombination { * For {@link MandatoryStreamInformation} belonging to other mandatory stream * combinations, the return value will be DEFAULT. </p> * - * @return the integer stream use case. + * @return the long integer stream use case. */ - public @StreamUseCase int getStreamUseCase() { + public @StreamUseCase long getStreamUseCase() { return mStreamUseCase; } @@ -365,15 +365,15 @@ public final class MandatoryStreamCombination { /** * Short hand for stream use cases */ - private static final int STREAM_USE_CASE_PREVIEW = + private static final long STREAM_USE_CASE_PREVIEW = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW; - private static final int STREAM_USE_CASE_STILL_CAPTURE = + private static final long STREAM_USE_CASE_STILL_CAPTURE = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE; - private static final int STREAM_USE_CASE_RECORD = + private static final long STREAM_USE_CASE_RECORD = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD; - private static final int STREAM_USE_CASE_PREVIEW_VIDEO_STILL = + private static final long STREAM_USE_CASE_PREVIEW_VIDEO_STILL = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL; - private static final int STREAM_USE_CASE_VIDEO_CALL = + private static final long STREAM_USE_CASE_VIDEO_CALL = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL; /** @@ -471,12 +471,12 @@ public final class MandatoryStreamCombination { private static final class StreamTemplate { public int mFormat; public SizeThreshold mSizeThreshold; - public int mStreamUseCase; + public long mStreamUseCase; public StreamTemplate(int format, SizeThreshold sizeThreshold) { this(format, sizeThreshold, CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT); } public StreamTemplate(@Format int format, @NonNull SizeThreshold sizeThreshold, - @StreamUseCase int streamUseCase) { + @StreamUseCase long streamUseCase) { mFormat = format; mSizeThreshold = sizeThreshold; mStreamUseCase = streamUseCase; diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 2350b7c7a481..39cb7f3ebddb 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -918,9 +918,9 @@ public final class OutputConfiguration implements Parcelable { * @throws IllegalArgumentException If the streamUseCase isn't within the range of valid * values. */ - public void setStreamUseCase(@StreamUseCase int streamUseCase) { + public void setStreamUseCase(@StreamUseCase long streamUseCase) { // Verify that the value is in range - int maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL; + long maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL; if (streamUseCase > maxUseCaseValue && streamUseCase < CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) { throw new IllegalArgumentException("Not a valid stream use case value " + @@ -938,7 +938,7 @@ public final class OutputConfiguration implements Parcelable { * * @return the currently set stream use case */ - public int getStreamUseCase() { + public long getStreamUseCase() { return mStreamUseCase; } @@ -1067,7 +1067,7 @@ public final class OutputConfiguration implements Parcelable { String physicalCameraId = source.readString(); boolean isMultiResolutionOutput = source.readInt() == 1; int[] sensorPixelModesUsed = source.createIntArray(); - int streamUseCase = source.readInt(); + long streamUseCase = source.readLong(); checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant"); long dynamicRangeProfile = source.readLong(); @@ -1218,7 +1218,7 @@ public final class OutputConfiguration implements Parcelable { // writeList doesn't seem to work well with Integer list. dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed)); dest.writeLong(mDynamicRangeProfile); - dest.writeInt(mStreamUseCase); + dest.writeLong(mStreamUseCase); dest.writeInt(mTimestampBase); dest.writeInt(mMirrorMode); } @@ -1337,7 +1337,7 @@ public final class OutputConfiguration implements Parcelable { // Dynamic range profile private long mDynamicRangeProfile; // Stream use case - private int mStreamUseCase; + private long mStreamUseCase; // Timestamp base private int mTimestampBase; // Mirroring mode diff --git a/core/java/android/inputmethodservice/InkWindow.java b/core/java/android/inputmethodservice/InkWindow.java index 499634ae5bec..8289c268d4c6 100644 --- a/core/java/android/inputmethodservice/InkWindow.java +++ b/core/java/android/inputmethodservice/InkWindow.java @@ -27,6 +27,8 @@ import android.content.Context; import android.os.IBinder; import android.util.Slog; import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.WindowManager; import com.android.internal.policy.PhoneWindow; @@ -40,6 +42,9 @@ final class InkWindow extends PhoneWindow { private final WindowManager mWindowManager; private boolean mIsViewAdded; + private View mInkView; + private InkVisibilityListener mInkViewVisibilityListener; + private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener; public InkWindow(@NonNull Context context) { super(context); @@ -102,4 +107,77 @@ final class InkWindow extends PhoneWindow { lp.token = token; setAttributes(lp); } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + if (mInkView == null) { + mInkView = view; + } else if (mInkView != view) { + throw new IllegalStateException("Only one Child Inking view is permitted."); + } + super.addContentView(view, params); + initInkViewVisibilityListener(); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + mInkView = view; + super.setContentView(view, params); + initInkViewVisibilityListener(); + } + + @Override + public void setContentView(View view) { + mInkView = view; + super.setContentView(view); + initInkViewVisibilityListener(); + } + + @Override + public void clearContentView() { + if (mGlobalLayoutListener != null && mInkView != null) { + mInkView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener); + } + mGlobalLayoutListener = null; + mInkView = null; + super.clearContentView(); + } + + /** + * Listener used by InkWindow to time the dispatching of {@link MotionEvent}s to Ink view, once + * it is visible to user. + */ + interface InkVisibilityListener { + void onInkViewVisible(); + } + + void setInkViewVisibilityListener(InkVisibilityListener listener) { + mInkViewVisibilityListener = listener; + initInkViewVisibilityListener(); + } + + void initInkViewVisibilityListener() { + if (mInkView == null || mInkViewVisibilityListener == null + || mGlobalLayoutListener != null) { + return; + } + mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (mInkView.isVisibleToUser()) { + if (mInkViewVisibilityListener != null) { + mInkViewVisibilityListener.onInkViewVisible(); + } + mInkView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + mGlobalLayoutListener = null; + } + } + }; + mInkView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener); + } + + boolean isInkViewVisible() { + return getDecorView().getVisibility() == View.VISIBLE + && mInkView != null && mInkView.isVisibleToUser(); + } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 656aea18fe50..b46bb3257c86 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -143,6 +143,7 @@ import com.android.internal.inputmethod.ImeTracing; import com.android.internal.inputmethod.InputMethodNavButtonFlags; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; +import com.android.internal.util.RingBuffer; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.IInputContext; import com.android.internal.view.InlineSuggestionsRequestInfo; @@ -334,6 +335,17 @@ public class InputMethodService extends AbstractInputMethodService { "persist.sys.ime.can_render_gestural_nav_buttons"; /** + * Number of {@link MotionEvent} to buffer if IME is not ready with Ink view. + * This number may be configured eventually based on device's touch sampling frequency. + */ + private static final int MAX_EVENTS_BUFFER = 500; + + /** + * A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view. + **/ + private RingBuffer<MotionEvent> mPendingEvents; + + /** * Returns whether {@link InputMethodService} is responsible for rendering the back button and * the IME switcher button or not when the gestural navigation is enabled. * @@ -954,7 +966,8 @@ public class InputMethodService extends AbstractInputMethodService { mInkWindow.show(); // deliver previous @param stylusEvents - stylusEvents.forEach(mInkWindow.getDecorView()::dispatchTouchEvent); + stylusEvents.forEach(InputMethodService.this::onStylusHandwritingMotionEvent); + // create receiver for channel mHandwritingEventReceiver = new SimpleBatchedInputEventReceiver( channel, @@ -963,11 +976,11 @@ public class InputMethodService extends AbstractInputMethodService { if (!(event instanceof MotionEvent)) { return false; } - return mInkWindow.getDecorView().dispatchTouchEvent((MotionEvent) event); + onStylusHandwritingMotionEvent((MotionEvent) event); + return true; }); } - /** * {@inheritDoc} * @hide @@ -2357,7 +2370,8 @@ public class InputMethodService extends AbstractInputMethodService { * * If the IME supports handwriting for the current input, it should return {@code true}, * ensure its inking views are attached to the {@link #getStylusHandwritingWindow()}, and handle - * stylus input received on the ink window via {@link #getCurrentInputConnection()}. + * stylus input received from {@link #onStylusHandwritingMotionEvent(MotionEvent)} on the + * {@link #getStylusHandwritingWindow()} via {@link #getCurrentInputConnection()}. * @return {@code true} if IME can honor the request, {@code false} if IME cannot at this time. */ public boolean onStartStylusHandwriting() { @@ -2366,6 +2380,33 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * Called after {@link #onStartStylusHandwriting()} returns {@code true} for every Stylus + * {@link MotionEvent}. + * By default, this method forwards all {@link MotionEvent}s to the + * {@link #getStylusHandwritingWindow()} once its visible, however IME can override it to + * receive them sooner. + * @param motionEvent {@link MotionEvent} from stylus. + */ + public void onStylusHandwritingMotionEvent(@NonNull MotionEvent motionEvent) { + if (mInkWindow.isInkViewVisible()) { + mInkWindow.getDecorView().dispatchTouchEvent(motionEvent); + } else { + if (mPendingEvents == null) { + mPendingEvents = new RingBuffer(MotionEvent.class, MAX_EVENTS_BUFFER); + } + mPendingEvents.append(motionEvent); + mInkWindow.setInkViewVisibilityListener(() -> { + if (mPendingEvents != null && !mPendingEvents.isEmpty()) { + for (MotionEvent event : mPendingEvents.toArray()) { + mInkWindow.getDecorView().dispatchTouchEvent(event); + } + mPendingEvents.clear(); + } + }); + } + } + + /** * Called when the current stylus handwriting session was finished (either by the system or * via {@link #finishStylusHandwriting()}. * diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java index 2dd3aaa1f55a..5c9989e9d981 100644 --- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java +++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java @@ -27,6 +27,7 @@ import static android.net.NetworkStats.TAG_NONE; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import android.annotation.NonNull; +import android.annotation.StringDef; import android.annotation.SystemApi; import android.net.NetworkIdentity; import android.net.NetworkStatsCollection; @@ -47,6 +48,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.ProtocolException; import java.util.ArrayList; import java.util.HashMap; @@ -76,6 +79,15 @@ public class NetworkStatsDataMigrationUtils { */ public static final String PREFIX_UID_TAG = "uid_tag"; + /** @hide */ + @StringDef(prefix = {"PREFIX_"}, value = { + PREFIX_XT, + PREFIX_UID, + PREFIX_UID_TAG, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Prefix {} + private static final HashMap<String, String> sPrefixLegacyFileNameMap = new HashMap<String, String>() {{ put(PREFIX_XT, "netstats_xt.bin"); @@ -141,13 +153,13 @@ public class NetworkStatsDataMigrationUtils { // Get /data/system/netstats_*.bin legacy files. Does not check for existence. @NonNull - private static File getLegacyBinFileForPrefix(@NonNull String prefix) { + private static File getLegacyBinFileForPrefix(@NonNull @Prefix String prefix) { return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix)); } // List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files. @NonNull - private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) { + private static ArrayList<File> getPlatformFileListForPrefix(@NonNull @Prefix String prefix) { final ArrayList<File> list = new ArrayList<>(); final File platformFiles = new File(getPlatformBaseDir(), "netstats"); if (platformFiles.exists()) { @@ -207,7 +219,7 @@ public class NetworkStatsDataMigrationUtils { */ @NonNull public static NetworkStatsCollection readPlatformCollection( - @NonNull String prefix, long bucketDuration) throws IOException { + @NonNull @Prefix String prefix, long bucketDuration) throws IOException { final NetworkStatsCollection.Builder builder = new NetworkStatsCollection.Builder(bucketDuration); diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java index de76c8fab69b..f4ca1b50fe86 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -165,6 +165,7 @@ public abstract class BatteryConsumer { PROCESS_STATE_FOREGROUND, PROCESS_STATE_BACKGROUND, PROCESS_STATE_FOREGROUND_SERVICE, + PROCESS_STATE_CACHED, }) @Retention(RetentionPolicy.SOURCE) public @interface ProcessState { @@ -175,8 +176,9 @@ public abstract class BatteryConsumer { public static final int PROCESS_STATE_FOREGROUND = 1; public static final int PROCESS_STATE_BACKGROUND = 2; public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3; + public static final int PROCESS_STATE_CACHED = 4; - public static final int PROCESS_STATE_COUNT = 4; + public static final int PROCESS_STATE_COUNT = 5; private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT]; @@ -186,6 +188,7 @@ public abstract class BatteryConsumer { sProcessStateNames[PROCESS_STATE_FOREGROUND] = "fg"; sProcessStateNames[PROCESS_STATE_BACKGROUND] = "bg"; sProcessStateNames[PROCESS_STATE_FOREGROUND_SERVICE] = "fgs"; + sProcessStateNames[PROCESS_STATE_CACHED] = "cached"; } private static final int[] SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE = { diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index de1dc8091b2a..06c35b5bec5d 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -680,6 +680,8 @@ public abstract class BatteryStats implements Parcelable { return BatteryConsumer.PROCESS_STATE_BACKGROUND; case BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE: return BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE; + case BatteryStats.Uid.PROCESS_STATE_CACHED: + return BatteryConsumer.PROCESS_STATE_CACHED; default: return BatteryConsumer.PROCESS_STATE_UNSPECIFIED; } @@ -2681,7 +2683,7 @@ public abstract class BatteryStats implements Parcelable { public static final String[] RADIO_ACCESS_TECHNOLOGY_NAMES = {"Other", "LTE", "NR"}; /** - * Returns the time in microseconds that the mobile radio has been active on a + * Returns the time in milliseconds that the mobile radio has been active on a * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given * transmission power level. * @@ -2700,6 +2702,46 @@ public abstract class BatteryStats implements Parcelable { @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs); + /** + * Returns the time in milliseconds that the mobile radio has been actively transmitting data on + * a given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given + * transmission power level. + * + * @param rat Radio Access Technology {@see RadioAccessTechnology} + * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for + * RADIO_ACCESS_TECHNOLOGY_NR. Use + * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access + * Technologies. + * @param signalStrength the cellular signal strength. {@see CellSignalStrength#getLevel()} + * @param elapsedRealtimeMs current elapsed realtime + * @return time (in milliseconds) the mobile radio spent actively transmitting data in the + * specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if + * data unavailable. + * @hide + */ + public abstract long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat, + @ServiceState.FrequencyRange int frequencyRange, int signalStrength, + long elapsedRealtimeMs); + + /** + * Returns the time in milliseconds that the mobile radio has been actively receiving data on a + * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given + * transmission power level. + * + * @param rat Radio Access Technology {@see RadioAccessTechnology} + * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for + * RADIO_ACCESS_TECHNOLOGY_NR. Use + * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access + * Technologies. + * @param elapsedRealtimeMs current elapsed realtime + * @return time (in milliseconds) the mobile radio spent actively receiving data in the + * specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if + * data unavailable. + * @hide + */ + public abstract long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat, + @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs); + static final String[] WIFI_SUPPL_STATE_NAMES = { "invalid", "disconn", "disabled", "inactive", "scanning", "authenticating", "associating", "associated", "4-way-handshake", @@ -2720,6 +2762,13 @@ public abstract class BatteryStats implements Parcelable { public static final long POWER_DATA_UNAVAILABLE = -1L; /** + * Returned value if duration data is unavailable. + * + * {@hide} + */ + public static final long DURATION_UNAVAILABLE = -1L; + + /** * Returns the battery consumption (in microcoulombs) of bluetooth, derived from on * device power measurement data. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. @@ -4093,6 +4142,10 @@ public abstract class BatteryStats implements Parcelable { " Mmwave frequency (greater than 6GHz):\n"}; final String signalStrengthHeader = " Signal Strength Time:\n"; + final String txHeader = + " Tx Time:\n"; + final String rxHeader = + " Rx Time: "; final String[] signalStrengthDescription = new String[]{ " unknown: ", " poor: ", @@ -4144,6 +4197,29 @@ public abstract class BatteryStats implements Parcelable { sb.append(")\n"); } + sb.append(prefix); + sb.append(txHeader); + for (int strength = 0; strength < numSignalStrength; strength++) { + final long timeMs = getActiveTxRadioDurationMs(rat, freqLvl, strength, + rawRealtimeMs); + if (timeMs <= 0) continue; + hasFreqData = true; + sb.append(prefix); + sb.append(signalStrengthDescription[strength]); + formatTimeMs(sb, timeMs); + sb.append("("); + sb.append(formatRatioLocked(timeMs, totalActiveTimesMs)); + sb.append(")\n"); + } + + sb.append(prefix); + sb.append(rxHeader); + final long rxTimeMs = getActiveRxRadioDurationMs(rat, freqLvl, rawRealtimeMs); + formatTimeMs(sb, rxTimeMs); + sb.append("("); + sb.append(formatRatioLocked(rxTimeMs, totalActiveTimesMs)); + sb.append(")\n"); + if (hasFreqData) { hasData = true; pw.print(sb); @@ -5655,6 +5731,7 @@ public abstract class BatteryStats implements Parcelable { .setMaxStatsAgeMs(0) .includePowerModels() .includeProcessStateData() + .includeVirtualUids() .build()); stats.dump(pw, prefix); diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java index 37bd51bb66c5..b3f4d9874f4e 100644 --- a/core/java/android/os/BatteryUsageStatsQuery.java +++ b/core/java/android/os/BatteryUsageStatsQuery.java @@ -42,6 +42,7 @@ public final class BatteryUsageStatsQuery implements Parcelable { FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL, FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY, FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA, + FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS, }) @Retention(RetentionPolicy.SOURCE) public @interface BatteryUsageStatsFlags {} @@ -69,6 +70,8 @@ public final class BatteryUsageStatsQuery implements Parcelable { public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA = 0x0008; + public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS = 0x0010; + private static final long DEFAULT_MAX_STATS_AGE_MS = 5 * 60 * 1000; private final int mFlags; @@ -271,6 +274,15 @@ public final class BatteryUsageStatsQuery implements Parcelable { } /** + * Requests to return attribution data for virtual UIDs such as + * {@link Process#SDK_SANDBOX_VIRTUAL_UID}. + */ + public Builder includeVirtualUids() { + mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS; + return this; + } + + /** * Requests to aggregate stored snapshots between the two supplied timestamps * @param fromTimestamp Exclusive starting timestamp, as per System.currentTimeMillis() * @param toTimestamp Inclusive ending timestamp, as per System.currentTimeMillis() diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index a19b51b7811b..cf28c1639fac 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -989,7 +989,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * Otherwise, this method might throw an exception or return {@code null}. * * @param key a String, or {@code null} - * @param clazz The type of the items inside the array + * @param clazz The type of the items inside the array. This is only verified when unparceling. * @return a Parcelable[] value, or {@code null} */ @SuppressLint({"ArrayReturn", "NullableCollection"}) @@ -1053,7 +1053,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * Otherwise, this method might throw an exception or return {@code null}. * * @param key a String, or {@code null} - * @param clazz The type of the items inside the array list + * @param clazz The type of the items inside the array list. This is only verified when + * unparceling. * @return an ArrayList<T> value, or {@code null} */ @SuppressLint("NullableCollection") @@ -1103,6 +1104,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * </ul> * * @param key a String, or null + * @param clazz The type of the items inside the sparse array. This is only verified when + * unparceling. * @return a SparseArray of T values, or null */ @SuppressWarnings("unchecked") diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 0a7a40798d71..ecdc803c0074 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -478,10 +478,20 @@ public class Environment { } /** {@hide} */ + public static File getDataMiscCeSharedSdkSandboxDirectory(int userId, String packageName) { + return buildPath(getDataMiscCeDirectory(userId), "sdksandbox", packageName, "shared"); + } + + /** {@hide} */ public static File getDataMiscDeDirectory(int userId) { return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId)); } + /** {@hide} */ + public static File getDataMiscDeSharedSdkSandboxDirectory(int userId, String packageName) { + return buildPath(getDataMiscDeDirectory(userId), "sdksandbox", packageName, "shared"); + } + private static File getDataProfilesDeDirectory(int userId) { return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId)); } 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/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java index 368ee2d91172..a739ba3dd438 100644 --- a/core/java/android/os/ParcelableHolder.java +++ b/core/java/android/os/ParcelableHolder.java @@ -179,7 +179,11 @@ public final class ParcelableHolder implements Parcelable { * Read ParcelableHolder from a parcel. */ public void readFromParcel(@NonNull Parcel parcel) { - this.mStability = parcel.readInt(); + int wireStability = parcel.readInt(); + if (this.mStability != wireStability) { + throw new IllegalArgumentException("Expected stability " + this.mStability + + " but got " + wireStability); + } mParcelable = null; diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java index 605171208fc1..522807b83d04 100644 --- a/core/java/android/os/PowerComponents.java +++ b/core/java/android/os/PowerComponents.java @@ -292,6 +292,10 @@ class PowerComponents { procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice .FOREGROUND_SERVICE; break; + case BatteryConsumer.PROCESS_STATE_CACHED: + procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice + .CACHED; + break; default: throw new IllegalArgumentException("Unknown process state: " + processState); } diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java index a1ff923e3b94..91d231eb1c39 100644 --- a/core/java/android/os/UidBatteryConsumer.java +++ b/core/java/android/os/UidBatteryConsumer.java @@ -119,6 +119,8 @@ public final class UidBatteryConsumer extends BatteryConsumer { skipEmptyComponents); appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE, skipEmptyComponents); + appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_CACHED, + skipEmptyComponents); pw.print(sb); } @@ -202,20 +204,24 @@ public final class UidBatteryConsumer extends BatteryConsumer { private static final String PACKAGE_NAME_UNINITIALIZED = ""; private final BatteryStats.Uid mBatteryStatsUid; private final int mUid; + private final boolean mIsVirtualUid; private String mPackageWithHighestDrain = PACKAGE_NAME_UNINITIALIZED; private boolean mExcludeFromBatteryUsageStats; public Builder(BatteryConsumerData data, @NonNull BatteryStats.Uid batteryStatsUid) { - super(data, CONSUMER_TYPE_UID); - mBatteryStatsUid = batteryStatsUid; - mUid = batteryStatsUid.getUid(); - data.putLong(COLUMN_INDEX_UID, mUid); + this(data, batteryStatsUid, batteryStatsUid.getUid()); } public Builder(BatteryConsumerData data, int uid) { + this(data, null, uid); + } + + private Builder(BatteryConsumerData data, @Nullable BatteryStats.Uid batteryStatsUid, + int uid) { super(data, CONSUMER_TYPE_UID); - mBatteryStatsUid = null; + mBatteryStatsUid = batteryStatsUid; mUid = uid; + mIsVirtualUid = mUid == Process.SDK_SANDBOX_VIRTUAL_UID; data.putLong(COLUMN_INDEX_UID, mUid); } @@ -232,6 +238,10 @@ public final class UidBatteryConsumer extends BatteryConsumer { return mUid; } + public boolean isVirtualUid() { + return mIsVirtualUid; + } + /** * Sets the name of the package owned by this UID that consumed the highest amount * of power since BatteryStats reset. diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a715c6961359..2448a0504302 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1703,12 +1703,40 @@ public class UserManager { /** * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that - * an error occurred that prevented the user from being removed or set as ephemeral. + * an unknown error occurred that prevented the user from being removed or set as ephemeral. * * @hide */ @SystemApi - public static final int REMOVE_RESULT_ERROR = 3; + public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; + + /** + * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that + * the user could not be removed due to a {@link #DISALLOW_REMOVE_MANAGED_PROFILE} or + * {@link #DISALLOW_REMOVE_USER} user restriction. + * + * @hide + */ + @SystemApi + public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2; + + /** + * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that + * user being removed does not exist. + * + * @hide + */ + @SystemApi + public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; + + /** + * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that + * user being removed is a {@link UserHandle#SYSTEM} user which can't be removed. + * + * @hide + */ + @SystemApi + public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; /** * Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}. @@ -1719,7 +1747,10 @@ public class UserManager { REMOVE_RESULT_REMOVED, REMOVE_RESULT_DEFERRED, REMOVE_RESULT_ALREADY_BEING_REMOVED, - REMOVE_RESULT_ERROR, + REMOVE_RESULT_ERROR_USER_RESTRICTION, + REMOVE_RESULT_ERROR_USER_NOT_FOUND, + REMOVE_RESULT_ERROR_SYSTEM_USER, + REMOVE_RESULT_ERROR_UNKNOWN, }) @Retention(RetentionPolicy.SOURCE) public @interface RemoveResult {} @@ -4763,7 +4794,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 +4807,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(); } @@ -4846,8 +4877,10 @@ public class UserManager { * the {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction * * @return the {@link RemoveResult} code: {@link #REMOVE_RESULT_REMOVED}, - * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, or - * {@link #REMOVE_RESULT_ERROR}. + * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, + * {@link #REMOVE_RESULT_ERROR_USER_RESTRICTION}, {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND}, + * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, or {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error + * codes have negative values. * * @hide */ @@ -4864,6 +4897,19 @@ public class UserManager { } /** + * Check if {@link #removeUserWhenPossible} returned a success code which means that the user + * has been removed or is slated for removal. + * + * @param result is {@link #RemoveResult} code return by {@link #removeUserWhenPossible}. + * @return {@code true} if it is a success code. + * @hide + */ + @SystemApi + public static boolean isRemoveResultSuccessful(@RemoveResult int result) { + return result >= 0; + } + + /** * Updates the user's name. * * @param userId the user's integer id diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index 7832dccd93a5..c021c079ae2e 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -78,37 +78,10 @@ interface IStorageManager { */ String getMountedObbPath(in String rawPath) = 24; /** - * Decrypts any encrypted volumes. - */ - int decryptStorage(in String password) = 26; - /** - * Encrypts storage. - */ - int encryptStorage(int type, in String password) = 27; - /** - * Changes the encryption password. - */ - int changeEncryptionPassword(int type, in String password) = 28; - /** * Returns list of all mountable volumes for the specified userId */ StorageVolume[] getVolumeList(int userId, in String callingPackage, int flags) = 29; /** - * Determines the encryption state of the volume. - * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible - * values. - * Note that this has been replaced in most cases by the APIs in - * StorageManager (see isEncryptable and below) - * This is still useful to get the error state when encryption has failed - * and CryptKeeper needs to throw up a screen advising the user what to do - */ - int getEncryptionState() = 31; - /** - * Verify the encryption password against the stored volume. This method - * may only be called by the system process. - */ - int verifyEncryptionPassword(in String password) = 32; - /** * Ensure that all directories along given path exist, creating parent * directories as needed. Validates that given path is absolute and that it * contains no relative "." or ".." paths or symlinks. Also ensures that @@ -117,32 +90,6 @@ interface IStorageManager { */ void mkdirs(in String callingPkg, in String path) = 34; /** - * Determines the type of the encryption password - * @return PasswordType - */ - int getPasswordType() = 35; - /** - * Get password from vold - * @return password or empty string - */ - String getPassword() = 36; - /** - * Securely clear password from vold - */ - oneway void clearPassword() = 37; - /** - * Set a field in the crypto header. - * @param field field to set - * @param contents contents to set in field - */ - oneway void setField(in String field, in String contents) = 38; - /** - * Gets a field from the crypto header. - * @param field field to get - * @return contents of field - */ - String getField(in String field) = 39; - /** * Report the time of the last maintenance operation such as fstrim. * @return Timestamp of the last maintenance operation, in the * System.currentTimeMillis() time base diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 312abf877f53..9971cbcfa586 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -3044,14 +3044,4 @@ public class StorageManager { public static final int CRYPT_TYPE_PATTERN = IVold.PASSWORD_TYPE_PATTERN; /** @hide */ public static final int CRYPT_TYPE_PIN = IVold.PASSWORD_TYPE_PIN; - - // Constants for the data available via StorageManagerService.getField. - /** @hide */ - public static final String SYSTEM_LOCALE_KEY = "SystemLocale"; - /** @hide */ - public static final String OWNER_INFO_KEY = "OwnerInfo"; - /** @hide */ - public static final String PATTERN_VISIBLE_KEY = "PatternVisible"; - /** @hide */ - public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible"; } diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 052e4d0538f2..47315047b6c4 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -74,6 +74,13 @@ public final class DeviceConfig { public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager"; /** + * Namespace for activity manager, specific to the "component alias" feature. We needed a + * different namespace in order to avoid phonetype from resetting it. + * @hide + */ + public static final String NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS = "activity_manager_ca"; + + /** * Namespace for all activity manager related features that are used at the native level. * These features are applied at reboot. * @@ -322,6 +329,13 @@ public final class DeviceConfig { public static final String NAMESPACE_NNAPI_NATIVE = "nnapi_native"; /** + * Namespace for all OnDevicePersonalization related feature. + * @hide + */ + @SystemApi + public static final String NAMESPACE_ON_DEVICE_PERSONALIZATION = "on_device_personalization"; + + /** * Namespace for features related to the Package Manager Service. * * @hide @@ -586,6 +600,13 @@ public final class DeviceConfig { public static final String NAMESPACE_SELECTION_TOOLBAR = "selection_toolbar"; /** + * Definitions for voice interaction related functions. + * + * @hide + */ + public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction"; + + /** * List of namespaces which can be read without READ_DEVICE_CONFIG permission * * @hide diff --git a/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java b/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java index 227194e60a7e..a216ed501687 100644 --- a/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java +++ b/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java @@ -26,6 +26,7 @@ import com.android.internal.util.AnnotationValidations; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Represents a {@code AmbientContextEvent} detection result reported by the detection service. @@ -127,7 +128,9 @@ public final class AmbientContextDetectionResult implements Parcelable { private @NonNull String mPackageName; private long mBuilderFieldsSet = 0L; - public Builder() { + public Builder(@NonNull String packageName) { + Objects.requireNonNull(packageName); + mPackageName = packageName; } /** @@ -144,26 +147,37 @@ public final class AmbientContextDetectionResult implements Parcelable { } /** - * The package to deliver the response to. + * Adds a list of events to the builder. */ - public @NonNull Builder setPackageName(@NonNull String value) { + public @NonNull Builder addEvents(@NonNull List<AmbientContextEvent> values) { checkNotUsed(); - mBuilderFieldsSet |= 0x2; - mPackageName = value; + if (mEvents == null) { + mBuilderFieldsSet |= 0x1; + mEvents = new ArrayList<>(); + } + mEvents.addAll(values); + return this; + } + + /** + * Clears all events from the builder. + */ + public @NonNull Builder clearEvents() { + checkNotUsed(); + if (mEvents != null) { + mEvents.clear(); + } return this; } /** Builds the instance. This builder should not be touched after calling this! */ public @NonNull AmbientContextDetectionResult build() { checkNotUsed(); - mBuilderFieldsSet |= 0x4; // Mark builder used + mBuilderFieldsSet |= 0x2; // Mark builder used if ((mBuilderFieldsSet & 0x1) == 0) { mEvents = new ArrayList<>(); } - if ((mBuilderFieldsSet & 0x2) == 0) { - mPackageName = ""; - } AmbientContextDetectionResult o = new AmbientContextDetectionResult( mEvents, mPackageName); @@ -171,7 +185,7 @@ public final class AmbientContextDetectionResult implements Parcelable { } private void checkNotUsed() { - if ((mBuilderFieldsSet & 0x4) != 0) { + if ((mBuilderFieldsSet & 0x2) != 0) { throw new IllegalStateException( "This Builder should not be reused. Use a new Builder instance instead"); } diff --git a/core/java/android/service/ambientcontext/AmbientContextDetectionService.java b/core/java/android/service/ambientcontext/AmbientContextDetectionService.java index 6224aa1d102e..8cf34115c6c4 100644 --- a/core/java/android/service/ambientcontext/AmbientContextDetectionService.java +++ b/core/java/android/service/ambientcontext/AmbientContextDetectionService.java @@ -134,12 +134,18 @@ public abstract class AmbientContextDetectionService extends Service { } /** - * Starts detection and provides detected events to the statusConsumer. The ongoing detection - * will keep running, until onStopDetection is called. If there were previously requested - * detection from the same package, the previous request will be replaced with the new request. - * The implementation should keep track of whether the user consented each requested - * AmbientContextEvent for the app. If not consented, the statusConsumer should get a response - * with STATUS_ACCESS_DENIED. + * Called when a client app requests starting detection of the events in the request. The + * implementation should keep track of whether the user has explicitly consented to detecting + * the events using on-going ambient sensor (e.g. microphone), and agreed to share the + * detection results with this client app. If the user has not consented, the detection + * should not start, and the statusConsumer should get a response with STATUS_ACCESS_DENIED. + * If the user has made the consent and the underlying services are available, the + * implementation should start detection and provide detected events to the + * detectionResultConsumer. If the type of event needs immediate attention, the implementation + * should send result as soon as detected. Otherwise, the implementation can bulk send response. + * The ongoing detection will keep running, until onStopDetection is called. If there were + * previously requested detection from the same package, regardless of the type of events in + * the request, the previous request will be replaced with the new request. * * @param request The request with events to detect. * @param packageName the requesting app's package name diff --git a/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java b/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java index 3e92f39893de..199e674e4b54 100644 --- a/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java +++ b/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java @@ -24,6 +24,8 @@ import android.os.Parcelable; import com.android.internal.util.AnnotationValidations; +import java.util.Objects; + /** * Represents a status for the {@code AmbientContextDetectionService}. * @@ -121,7 +123,9 @@ public final class AmbientContextDetectionServiceStatus implements Parcelable { private @NonNull String mPackageName; private long mBuilderFieldsSet = 0L; - public Builder() { + public Builder(@NonNull String packageName) { + Objects.requireNonNull(packageName); + mPackageName = packageName; } /** @@ -134,27 +138,14 @@ public final class AmbientContextDetectionServiceStatus implements Parcelable { return this; } - /** - * The package to deliver the response to. - */ - public @NonNull Builder setPackageName(@NonNull String value) { - checkNotUsed(); - mBuilderFieldsSet |= 0x2; - mPackageName = value; - return this; - } - /** Builds the instance. This builder should not be touched after calling this! */ public @NonNull AmbientContextDetectionServiceStatus build() { checkNotUsed(); - mBuilderFieldsSet |= 0x4; // Mark builder used + mBuilderFieldsSet |= 0x2; // Mark builder used if ((mBuilderFieldsSet & 0x1) == 0) { mStatusCode = AmbientContextManager.STATUS_UNKNOWN; } - if ((mBuilderFieldsSet & 0x2) == 0) { - mPackageName = ""; - } AmbientContextDetectionServiceStatus o = new AmbientContextDetectionServiceStatus( mStatusCode, mPackageName); @@ -162,7 +153,7 @@ public final class AmbientContextDetectionServiceStatus implements Parcelable { } private void checkNotUsed() { - if ((mBuilderFieldsSet & 0x4) != 0) { + if ((mBuilderFieldsSet & 0x2) != 0) { throw new IllegalStateException( "This Builder should not be reused. Use a new Builder instance instead"); } diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index b507328d21a1..0829d2813c83 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -15,18 +15,19 @@ */ package android.service.quicksettings; -import android.Manifest; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.Dialog; import android.app.Service; +import android.app.StatusBarManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Icon; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -147,13 +148,6 @@ public class TileService extends Service { "android.service.quicksettings.TOGGLEABLE_TILE"; /** - * Used to notify SysUI that Listening has be requested. - * @hide - */ - public static final String ACTION_REQUEST_LISTENING = - "android.service.quicksettings.action.REQUEST_LISTENING"; - - /** * @hide */ public static final String EXTRA_SERVICE = "service"; @@ -482,14 +476,24 @@ public class TileService extends Service { * * This method is only applicable to tiles that have {@link #META_DATA_ACTIVE_TILE} defined * as true on their TileService Manifest declaration, and will do nothing otherwise. + * + * For apps targeting {@link Build.VERSION_CODES#TIRAMISU} or later, this call may throw + * the following exceptions if the request is not valid: + * <ul> + * <li> {@link NullPointerException} if {@code component} is {@code null}.</li> + * <li> {@link SecurityException} if the package of {@code component} does not match + * the calling package or if the calling user cannot act on behalf of the user from the + * {@code context}.</li> + * <li> {@link IllegalArgumentException} if the user of the {@code context} is not the + * current user.</li> + * </ul> */ public static final void requestListeningState(Context context, ComponentName component) { - final ComponentName sysuiComponent = ComponentName.unflattenFromString( - context.getResources().getString( - com.android.internal.R.string.config_systemUIServiceComponent)); - Intent intent = new Intent(ACTION_REQUEST_LISTENING); - intent.putExtra(Intent.EXTRA_COMPONENT_NAME, component); - intent.setPackage(sysuiComponent.getPackageName()); - context.sendBroadcast(intent, Manifest.permission.BIND_QUICK_SETTINGS_TILE); + StatusBarManager sbm = context.getSystemService(StatusBarManager.class); + if (sbm == null) { + Log.e(TAG, "No StatusBarManager service found"); + return; + } + sbm.requestTileServiceListeningState(component); } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index a2938a8783eb..ef792d4c5e64 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -252,6 +252,7 @@ public abstract class WallpaperService extends Service { final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities(); final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0]; final MergedConfiguration mMergedConfiguration = new MergedConfiguration(); + final Bundle mSyncSeqIdBundle = new Bundle(); private final Point mSurfaceSize = new Point(); private final Point mLastSurfaceSize = new Point(); private final Matrix mTmpMatrix = new Matrix(); @@ -391,7 +392,7 @@ public abstract class WallpaperService extends Service { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) { Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0, mergedConfiguration); @@ -1151,7 +1152,7 @@ public abstract class WallpaperService extends Service { final int relayoutResult = mSession.relayout( mWindow, mLayout, mWidth, mHeight, View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl, - mInsetsState, mTempControls); + mInsetsState, mTempControls, mSyncSeqIdBundle); final int transformHint = SurfaceControl.rotationToBufferTransform( (mDisplayInstallOrientation + mDisplay.getRotation()) % 4); @@ -1338,7 +1339,8 @@ public abstract class WallpaperService extends Service { mSurfaceCreated = true; if (redrawNeeded) { resetWindowPages(); - mSession.finishDrawing(mWindow, null /* postDrawTransaction */); + mSession.finishDrawing(mWindow, null /* postDrawTransaction */, + Integer.MAX_VALUE); processLocalColors(mPendingXOffset, mPendingXOffsetStep); notifyColorsChanged(); } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index c1fcd664f6fa..f8445921d3b0 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -27,6 +27,7 @@ import android.os.Binder; import android.os.Build; import android.os.RemoteException; import android.os.ServiceManager; +import android.service.carrier.CarrierService; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DisconnectCauses; @@ -36,6 +37,7 @@ import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; +import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.telephony.TelephonyManager.CarrierPrivilegesListener; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; @@ -44,17 +46,19 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.listeners.ListenerExecutor; -import com.android.internal.telephony.ICarrierPrivilegesListener; +import com.android.internal.telephony.ICarrierPrivilegesCallback; import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.ITelephonyRegistry; import java.lang.ref.WeakReference; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.Executor; +import java.util.stream.Collectors; /** * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update @@ -1260,34 +1264,78 @@ public class TelephonyRegistryManager { pkgName, attributionTag, callback, new int[0], notifyNow); } - private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub + // TODO(b/216549778): Remove listener logic once all clients switch to CarrierPrivilegesCallback + private static class CarrierPrivilegesCallbackWrapper extends ICarrierPrivilegesCallback.Stub implements ListenerExecutor { - private final WeakReference<CarrierPrivilegesListener> mListener; - private final Executor mExecutor; + // Either mListener or mCallback may be null, never both + @Nullable private final WeakReference<CarrierPrivilegesListener> mListener; + @Nullable private final WeakReference<CarrierPrivilegesCallback> mCallback; + @NonNull private final Executor mExecutor; + + CarrierPrivilegesCallbackWrapper( + @NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) { + mListener = null; + mCallback = new WeakReference<>(callback); + mExecutor = executor; + } - CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) { + CarrierPrivilegesCallbackWrapper( + @NonNull CarrierPrivilegesListener listener, @NonNull Executor executor) { mListener = new WeakReference<>(listener); + mCallback = null; mExecutor = executor; } @Override public void onCarrierPrivilegesChanged( - List<String> privilegedPackageNames, int[] privilegedUids) { - Binder.withCleanCallingIdentity( - () -> - executeSafely( - mExecutor, - mListener::get, - cpl -> - cpl.onCarrierPrivilegesChanged( - privilegedPackageNames, privilegedUids))); + @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) { + if (mListener != null) { + Binder.withCleanCallingIdentity( + () -> + executeSafely( + mExecutor, + mListener::get, + cpl -> + cpl.onCarrierPrivilegesChanged( + privilegedPackageNames, privilegedUids))); + } + + if (mCallback != null) { + // AIDL interface does not support Set, keep the List/Array and translate them here + Set<String> privilegedPkgNamesSet = Set.copyOf(privilegedPackageNames); + Set<Integer> privilegedUidsSet = Arrays.stream(privilegedUids).boxed().collect( + Collectors.toSet()); + Binder.withCleanCallingIdentity( + () -> + executeSafely( + mExecutor, + mCallback::get, + cpc -> + cpc.onCarrierPrivilegesChanged( + privilegedPkgNamesSet, privilegedUidsSet))); + } + } + + @Override + public void onCarrierServiceChanged(@Nullable String packageName, int uid) { + if (mCallback != null) { + Binder.withCleanCallingIdentity( + () -> + executeSafely( + mExecutor, + mCallback::get, + cpc -> cpc.onCarrierServiceChanged(packageName, uid))); + } } } - @GuardedBy("sCarrierPrivilegeListeners") - private static final WeakHashMap< - CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>> - sCarrierPrivilegeListeners = new WeakHashMap<>(); + // TODO(b/216549778): Change the map key to CarrierPrivilegesCallback once all clients switch to + // CarrierPrivilegesCallback. Before that, the key is either CarrierPrivilegesCallback or + // CarrierPrivilegesListener, no logic actually depends on the type. + @NonNull + @GuardedBy("sCarrierPrivilegeCallbacks") + private static final WeakHashMap<Object, WeakReference<CarrierPrivilegesCallbackWrapper>> + sCarrierPrivilegeCallbacks = new WeakHashMap<>(); /** * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to @@ -1297,7 +1345,11 @@ public class TelephonyRegistryManager { * @param logicalSlotIndex The SIM slot to listen on * @param executor The executor where {@code listener} will be invoked * @param listener The callback to register + * + * @deprecated Use {@link #addCarrierPrivilegesCallback} instead. This API will be removed + * prior to API finalization. */ + @Deprecated public void addCarrierPrivilegesListener( int logicalSlotIndex, @NonNull @CallbackExecutor Executor executor, @@ -1305,18 +1357,18 @@ public class TelephonyRegistryManager { if (listener == null || executor == null) { throw new IllegalArgumentException("listener and executor must be non-null"); } - synchronized (sCarrierPrivilegeListeners) { - WeakReference<CarrierPrivilegesListenerWrapper> existing = - sCarrierPrivilegeListeners.get(listener); + synchronized (sCarrierPrivilegeCallbacks) { + WeakReference<CarrierPrivilegesCallbackWrapper> existing = + sCarrierPrivilegeCallbacks.get(listener); if (existing != null && existing.get() != null) { Log.d(TAG, "addCarrierPrivilegesListener: listener already registered"); return; } - CarrierPrivilegesListenerWrapper wrapper = - new CarrierPrivilegesListenerWrapper(listener, executor); - sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper)); + CarrierPrivilegesCallbackWrapper wrapper = + new CarrierPrivilegesCallbackWrapper(listener, executor); + sCarrierPrivilegeCallbacks.put(listener, new WeakReference<>(wrapper)); try { - sRegistry.addCarrierPrivilegesListener( + sRegistry.addCarrierPrivilegesCallback( logicalSlotIndex, wrapper, mContext.getOpPackageName(), @@ -1331,19 +1383,84 @@ public class TelephonyRegistryManager { * Unregisters a {@link CarrierPrivilegesListener}. * * @param listener The callback to unregister + * + * @deprecated Use {@link #removeCarrierPrivilegesCallback} instead. The callback will prior + * to API finalization. */ + @Deprecated public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must be non-null"); } - synchronized (sCarrierPrivilegeListeners) { - WeakReference<CarrierPrivilegesListenerWrapper> ref = - sCarrierPrivilegeListeners.remove(listener); + synchronized (sCarrierPrivilegeCallbacks) { + WeakReference<CarrierPrivilegesCallbackWrapper> ref = + sCarrierPrivilegeCallbacks.remove(listener); if (ref == null) return; - CarrierPrivilegesListenerWrapper wrapper = ref.get(); + CarrierPrivilegesCallbackWrapper wrapper = ref.get(); if (wrapper == null) return; try { - sRegistry.removeCarrierPrivilegesListener(wrapper, mContext.getOpPackageName()); + sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to + * receive callbacks when the set of packages with carrier privileges changes. The callback will + * immediately be called with the latest state. + * + * @param logicalSlotIndex The SIM slot to listen on + * @param executor The executor where {@code listener} will be invoked + * @param callback The callback to register + */ + public void addCarrierPrivilegesCallback( + int logicalSlotIndex, + @NonNull @CallbackExecutor Executor executor, + @NonNull CarrierPrivilegesCallback callback) { + if (callback == null || executor == null) { + throw new IllegalArgumentException("callback and executor must be non-null"); + } + synchronized (sCarrierPrivilegeCallbacks) { + WeakReference<CarrierPrivilegesCallbackWrapper> existing = + sCarrierPrivilegeCallbacks.get(callback); + if (existing != null && existing.get() != null) { + Log.d(TAG, "addCarrierPrivilegesCallback: callback already registered"); + return; + } + CarrierPrivilegesCallbackWrapper wrapper = + new CarrierPrivilegesCallbackWrapper(callback, executor); + sCarrierPrivilegeCallbacks.put(callback, new WeakReference<>(wrapper)); + try { + sRegistry.addCarrierPrivilegesCallback( + logicalSlotIndex, + wrapper, + mContext.getOpPackageName(), + mContext.getAttributionTag()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Unregisters a {@link CarrierPrivilegesCallback}. + * + * @param callback The callback to unregister + */ + public void removeCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("listener must be non-null"); + } + synchronized (sCarrierPrivilegeCallbacks) { + WeakReference<CarrierPrivilegesCallbackWrapper> ref = + sCarrierPrivilegeCallbacks.remove(callback); + if (ref == null) return; + CarrierPrivilegesCallbackWrapper wrapper = ref.get(); + if (wrapper == null) return; + try { + sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1359,15 +1476,33 @@ public class TelephonyRegistryManager { */ public void notifyCarrierPrivilegesChanged( int logicalSlotIndex, - @NonNull List<String> privilegedPackageNames, - @NonNull int[] privilegedUids) { + @NonNull Set<String> privilegedPackageNames, + @NonNull Set<Integer> privilegedUids) { if (privilegedPackageNames == null || privilegedUids == null) { throw new IllegalArgumentException( "privilegedPackageNames and privilegedUids must be non-null"); } try { - sRegistry.notifyCarrierPrivilegesChanged( - logicalSlotIndex, privilegedPackageNames, privilegedUids); + // AIDL doesn't support Set yet. Convert Set to List/Array + List<String> pkgList = List.copyOf(privilegedPackageNames); + int[] uids = privilegedUids.stream().mapToInt(Number::intValue).toArray(); + sRegistry.notifyCarrierPrivilegesChanged(logicalSlotIndex, pkgList, uids); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Notify listeners that the {@link CarrierService} for current user has changed. + * + * @param logicalSlotIndex the SIM slot the change occurred on + * @param packageName the package name of the changed {@link CarrierService} + * @param uid the UID of the changed {@link CarrierService} + */ + public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName, + int uid) { + try { + sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java index 9307e566b5c3..f31a690c7774 100644 --- a/core/java/android/text/PrecomputedText.java +++ b/core/java/android/text/PrecomputedText.java @@ -99,7 +99,7 @@ public class PrecomputedText implements Spannable { private final @Layout.HyphenationFrequency int mHyphenationFrequency; // The line break configuration for calculating text wrapping. - private final @Nullable LineBreakConfig mLineBreakConfig; + private final @NonNull LineBreakConfig mLineBreakConfig; /** * A builder for creating {@link Params}. @@ -119,7 +119,7 @@ public class PrecomputedText implements Spannable { Layout.HYPHENATION_FREQUENCY_NORMAL; // The line break configuration for calculating text wrapping. - private @Nullable LineBreakConfig mLineBreakConfig; + private @NonNull LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; /** * Builder constructor. @@ -212,7 +212,7 @@ public class PrecomputedText implements Spannable { // For the external developers, use Builder instead. /** @hide */ public Params(@NonNull TextPaint paint, - @Nullable LineBreakConfig lineBreakConfig, + @NonNull LineBreakConfig lineBreakConfig, @NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy, @Layout.HyphenationFrequency int frequency) { @@ -260,11 +260,12 @@ public class PrecomputedText implements Spannable { } /** - * Return the line break configuration for this text. + * Returns the {@link LineBreakConfig} for this text. * - * @return the current line break configuration, null if no line break configuration is set. + * @return the current line break configuration. The {@link LineBreakConfig} with default + * values will be returned if no line break configuration is set. */ - public @Nullable LineBreakConfig getLineBreakConfig() { + public @NonNull LineBreakConfig getLineBreakConfig() { return mLineBreakConfig; } @@ -297,9 +298,9 @@ public class PrecomputedText implements Spannable { /** @hide */ public @CheckResultUsableResult int checkResultUsable(@NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy, - @Layout.HyphenationFrequency int frequency, @Nullable LineBreakConfig lbConfig) { + @Layout.HyphenationFrequency int frequency, @NonNull LineBreakConfig lbConfig) { if (mBreakStrategy == strategy && mHyphenationFrequency == frequency - && isLineBreakEquals(mLineBreakConfig, lbConfig) + && mLineBreakConfig.equals(lbConfig) && mPaint.equalsForTextMeasurement(paint)) { return mTextDir == textDir ? USABLE : NEED_RECOMPUTE; } else { @@ -308,29 +309,6 @@ public class PrecomputedText implements Spannable { } /** - * Check the two LineBreakConfig instances are equal. - * This method assumes they are equal if one parameter is null and the other parameter has - * a LineBreakStyle value of LineBreakConfig.LINE_BREAK_STYLE_NONE. - * - * @param o1 the first LineBreakConfig instance. - * @param o2 the second LineBreakConfig instance. - * @return true if the two LineBreakConfig instances are equal. - */ - private boolean isLineBreakEquals(LineBreakConfig o1, LineBreakConfig o2) { - if (Objects.equals(o1, o2)) { - return true; - } - if (o1 == null && (o2 != null - && o2.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) { - return true; - } else if (o2 == null && (o1 != null - && o1.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) { - return true; - } - return false; - } - - /** * Check if the same text layout. * * @return true if this and the given param result in the same text layout diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index b10fc37bff2f..2f85d2b63840 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -112,6 +112,7 @@ public class StaticLayout extends Layout { b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE; + b.mLineBreakConfig = LineBreakConfig.NONE; return b; } @@ -410,7 +411,8 @@ public class StaticLayout extends Layout { * * @param lineBreakConfig the line break configuration for text wrapping. * @return this builder, useful for chaining. - * @see android.widget.TextView#setLineBreakConfig + * @see android.widget.TextView#setLineBreakStyle + * @see android.widget.TextView#setLineBreakWordStyle */ @NonNull public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) { @@ -454,7 +456,7 @@ public class StaticLayout extends Layout { @Nullable private int[] mRightIndents; private int mJustificationMode; private boolean mAddLastLineLineSpacing; - private LineBreakConfig mLineBreakConfig; + private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); 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/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java index c1413beb0143..190adbdfd5db 100644 --- a/core/java/android/view/HandwritingInitiator.java +++ b/core/java/android/view/HandwritingInitiator.java @@ -249,19 +249,19 @@ public class HandwritingInitiator { return; } - Rect handwritingArea = getViewHandwritingArea(connectedView); - if (handwritingArea != null) { - if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) { - startHandwriting(connectedView); - } + final Rect handwritingArea = getViewHandwritingArea(connectedView); + if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) { + startHandwriting(connectedView); + } else { + reset(); } - reset(); } /** For test only. */ @VisibleForTesting public void startHandwriting(@NonNull View view) { mImm.startStylusHandwriting(view); + reset(); } /** @@ -287,7 +287,7 @@ public class HandwritingInitiator { final View connectedView = getConnectedView(); if (connectedView != null && connectedView.isAutoHandwritingEnabled()) { final Rect handwritingArea = getViewHandwritingArea(connectedView); - if (handwritingArea != null && contains(handwritingArea, x, y)) { + if (contains(handwritingArea, x, y)) { return connectedView; } } @@ -298,8 +298,7 @@ public class HandwritingInitiator { for (HandwritableViewInfo viewInfo : handwritableViewInfos) { final View view = viewInfo.getView(); if (!view.isAutoHandwritingEnabled()) continue; - final Rect rect = viewInfo.getHandwritingArea(); - if (rect != null && contains(rect, x, y)) { + if (contains(viewInfo.getHandwritingArea(), x, y)) { return viewInfo.getView(); } } @@ -315,12 +314,15 @@ public class HandwritingInitiator { private static Rect getViewHandwritingArea(@NonNull View view) { final ViewParent viewParent = view.getParent(); if (viewParent != null && view.isAttachedToWindow() && view.isAggregatedVisible()) { - Rect handwritingArea = view.getHandwritingArea(); - if (handwritingArea == null) { - handwritingArea = new Rect(0, 0, view.getWidth(), view.getHeight()); + final Rect localHandwritingArea = view.getHandwritingArea(); + final Rect globalHandwritingArea = new Rect(); + if (localHandwritingArea != null) { + globalHandwritingArea.set(localHandwritingArea); + } else { + globalHandwritingArea.set(0, 0, view.getWidth(), view.getHeight()); } - if (viewParent.getChildVisibleRect(view, handwritingArea, null)) { - return handwritingArea; + if (viewParent.getChildVisibleRect(view, globalHandwritingArea, null)) { + return globalHandwritingArea; } } return null; @@ -329,7 +331,8 @@ public class HandwritingInitiator { /** * Return true if the (x, y) is inside by the given {@link Rect}. */ - private boolean contains(@NonNull Rect rect, float x, float y) { + private boolean contains(@Nullable Rect rect, float x, float y) { + if (rect == null) return false; return x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom; } @@ -481,17 +484,18 @@ public class HandwritingInitiator { if (!mIsDirty) { return true; } - final Rect localRect = view.getHandwritingArea(); - if (localRect == null) { + final Rect handwritingArea = view.getHandwritingArea(); + if (handwritingArea == null) { return false; } ViewParent parent = view.getParent(); if (parent != null) { - final Rect newRect = new Rect(localRect); - if (parent.getChildVisibleRect(view, newRect, null /* offset */)) { - mHandwritingArea = newRect; - } else { + if (mHandwritingArea == null) { + mHandwritingArea = new Rect(); + } + mHandwritingArea.set(handwritingArea); + if (!parent.getChildVisibleRect(view, mHandwritingArea, null /* offset */)) { mHandwritingArea = null; } } diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 12421ed61b33..1f6cee6267b7 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -55,7 +55,8 @@ oneway interface IWindow { void resized(in ClientWindowFrames frames, boolean reportDraw, in MergedConfiguration newMergedConfiguration, - boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId); + boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, + int syncSeqId); /** * Called when the window insets configuration has changed. diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 5c7c844ae773..fd8690009a6d 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -104,7 +104,8 @@ interface IWindowSession { int requestedWidth, int requestedHeight, int viewVisibility, int flags, out ClientWindowFrames outFrames, out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl, - out InsetsState insetsState, out InsetsSourceControl[] activeControls); + out InsetsState insetsState, out InsetsSourceControl[] activeControls, + out Bundle bundle); /* * Notify the window manager that an application is relaunching and @@ -142,7 +143,8 @@ interface IWindowSession { * is null if there is no sync required. */ @UnsupportedAppUsage - oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction); + oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction, + int seqId); @UnsupportedAppUsage oneway void setInTouchMode(boolean showFocus); 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/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 64f5668d8c14..f3c65eae8ba8 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -64,6 +64,7 @@ import android.util.proto.ProtoOutputStream; import android.view.Surface.OutOfResourcesException; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; import com.android.internal.util.VirtualRefBasePtr; import dalvik.system.CloseGuard; @@ -2961,6 +2962,8 @@ public final class SurfaceControl implements Parcelable { @NonNull public Transaction setScale(@NonNull SurfaceControl sc, float scaleX, float scaleY) { checkPreconditions(sc); + Preconditions.checkArgument(scaleX >= 0, "Negative value passed in for scaleX"); + Preconditions.checkArgument(scaleY >= 0, "Negative value passed in for scaleY"); nativeSetScale(mNativeObject, sc.mNativeObject, scaleX, scaleY); return this; } @@ -3205,6 +3208,7 @@ public final class SurfaceControl implements Parcelable { public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) { checkPreconditions(sc); if (crop != null) { + Preconditions.checkArgument(crop.isValid(), "Crop isn't valid."); nativeSetWindowCrop(mNativeObject, sc.mNativeObject, crop.left, crop.top, crop.right, crop.bottom); } else { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c2229911bf12..1b8dc706371e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -12016,7 +12016,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Return the handwriting areas set on this view, in its local coordinates. - * Notice: the caller of this method should not modify the Rect returned. * @see #setHandwritingArea(Rect) * * @hide @@ -12025,7 +12024,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public Rect getHandwritingArea() { final ListenerInfo info = mListenerInfo; if (info != null) { - return info.mHandwritingArea; + return new Rect(info.mHandwritingArea); } return null; } @@ -15617,7 +15616,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event the KeyEvent object that defines the button action */ public boolean onKeyDown(int keyCode, KeyEvent event) { - if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) { + if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; } @@ -15674,7 +15673,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event The KeyEvent object that defines the button action. */ public boolean onKeyUp(int keyCode, KeyEvent event) { - if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) { + if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index bde761e59620..cdbf8b44140a 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. */ @@ -546,7 +552,6 @@ public final class ViewRootImpl implements ViewParent, private final Rect mVisRect = new Rect(); // used to retrieve visible rect of focused view. private final Rect mTempRect = new Rect(); - private final Rect mTempRect2 = new Rect(); private final WindowLayout mWindowLayout = new WindowLayout(); @@ -824,6 +829,24 @@ public final class ViewRootImpl implements ViewParent, private int mLastTransformHint = Integer.MIN_VALUE; + /** + * A temporary object used so relayoutWindow can return the latest SyncSeqId + * system. The SyncSeqId system was designed to work without synchronous relayout + * window, and actually synchronous relayout window presents a problem. We could have + * a sequence like this: + * 1. We send MSG_RESIZED to the client with a new syncSeqId to begin a new sync + * 2. Due to scheduling the client executes performTraversals before calling MSG_RESIZED + * 3. Coincidentally for some random reason it also calls relayout + * 4. It observes the new state from relayout, and so the next frame will contain the state + * However it hasn't received the seqId yet, and so under the designed operation of + * seqId flowing through MSG_RESIZED, the next frame wouldn't be synced. Since it + * contains our target sync state, we need to sync it! This problem won't come up once + * we get rid of synchronous relayout, until then, we use this bundle to channel the + * integer back over relayout. + */ + private Bundle mRelayoutBundle = new Bundle(); + private int mSyncSeqId; + private String mTag = TAG; public ViewRootImpl(Context context, Display display) { @@ -867,6 +890,7 @@ public final class ViewRootImpl implements ViewParent, mDensity = context.getResources().getDisplayMetrics().densityDpi; mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi; mFallbackEventHandler = new PhoneFallbackEventHandler(context); + // TODO(b/222696368): remove getSfInstance usage and use vsyncId for transactions mChoreographer = useSfChoreographer ? Choreographer.getSfInstance() : Choreographer.getInstance(); mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); @@ -1198,8 +1222,7 @@ public final class ViewRootImpl implements ViewParent, displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(), UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH, mInsetsController.getRequestedVisibilities(), - getAttachedWindowFrame(), 1f /* compactScale */, - mTmpFrames.displayFrame, mTempRect2, mTmpFrames.frame); + getAttachedWindowFrame(), 1f /* compactScale */, mTmpFrames); setFrame(mTmpFrames.frame); registerBackCallbackOnWindow(); if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) { @@ -1704,6 +1727,7 @@ public final class ViewRootImpl implements ViewParent, mPendingBackDropFrame.set(backdropFrame); mForceNextWindowRelayout = forceNextWindowRelayout; mPendingAlwaysConsumeSystemBars = args.argi2 != 0; + mSyncSeqId = args.argi4; if (msg == MSG_RESIZED_REPORT) { reportNextDraw(); @@ -1771,6 +1795,7 @@ public final class ViewRootImpl implements ViewParent, updateInternalDisplay(displayId, mView.getResources()); mImeFocusController.onMovedToDisplay(); mAttachInfo.mDisplayState = mDisplay.getState(); + mDisplayInstallOrientation = mDisplay.getInstallOrientation(); // Internal state updated, now notify the view hierarchy. mView.dispatchMovedToDisplay(mDisplay, config); } @@ -2561,6 +2586,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(); @@ -3439,6 +3467,12 @@ public final class ViewRootImpl implements ViewParent, mReportNextDraw = false; pendingDrawFinished(); } + + // Make sure the consumer is not waiting if the view root was just made invisible. + if (mBLASTDrawConsumer != null) { + mBLASTDrawConsumer.accept(null); + mBLASTDrawConsumer = null; + } } } @@ -4111,7 +4145,7 @@ public final class ViewRootImpl implements ViewParent, mDrawsNeededToReport = 0; try { - mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction); + mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE); } catch (RemoteException e) { Log.e(mTag, "Unable to report draw finished", e); mSurfaceChangedTransaction.apply(); @@ -8054,7 +8088,7 @@ public final class ViewRootImpl implements ViewParent, requestedWidth, requestedHeight, viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, - mTempControls); + mTempControls, mRelayoutBundle); final int transformHint = SurfaceControl.rotationToBufferTransform( (mDisplayInstallOrientation + mDisplay.getRotation()) % 4); @@ -8480,7 +8514,7 @@ public final class ViewRootImpl implements ViewParent, if ((relayoutWindow(mWindowAttributes, viewVisibility, false) & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mWindowSession.finishDrawing( - mWindow, null /* postDrawTransaction */); + mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE); } } catch (RemoteException e) { } @@ -8554,7 +8588,7 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private void dispatchResized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId) { final Rect frame = frames.frame; final Rect backDropFrame = frames.backdropFrame; if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString() @@ -8585,6 +8619,7 @@ public final class ViewRootImpl implements ViewParent, args.argi1 = forceLayout ? 1 : 0; args.argi2 = alwaysConsumeSystemBars ? 1 : 0; args.argi3 = displayId; + args.argi4 = seqId; msg.obj = args; mHandler.sendMessage(msg); } @@ -9969,11 +10004,11 @@ public final class ViewRootImpl implements ViewParent, @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout, - alwaysConsumeSystemBars, displayId); + alwaysConsumeSystemBars, displayId, seqId); } } diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java index ad9f21b4fa70..a3b1313202c2 100644 --- a/core/java/android/view/WindowLayout.java +++ b/core/java/android/view/WindowLayout.java @@ -42,6 +42,7 @@ import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.util.Log; +import android.window.ClientWindowFrames; /** * Computes window frames. @@ -56,15 +57,17 @@ public class WindowLayout { private final Rect mTempDisplayCutoutSafeExceptMaybeBarsRect = new Rect(); private final Rect mTempRect = new Rect(); - public boolean computeFrames(WindowManager.LayoutParams attrs, InsetsState state, + public void computeFrames(WindowManager.LayoutParams attrs, InsetsState state, Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode, int requestedWidth, int requestedHeight, InsetsVisibilities requestedVisibilities, - Rect attachedWindowFrame, float compatScale, Rect outDisplayFrame, Rect outParentFrame, - Rect outFrame) { + Rect attachedWindowFrame, float compatScale, ClientWindowFrames outFrames) { final int type = attrs.type; final int fl = attrs.flags; final int pfl = attrs.privateFlags; final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN; + final Rect outDisplayFrame = outFrames.displayFrame; + final Rect outParentFrame = outFrames.parentFrame; + final Rect outFrame = outFrames.frame; // Compute bounds restricted by insets final Insets insets = state.calculateInsets(windowBounds, attrs.getFitInsetsTypes(), @@ -95,7 +98,7 @@ public class WindowLayout { final DisplayCutout cutout = state.getDisplayCutout(); final Rect displayCutoutSafeExceptMaybeBars = mTempDisplayCutoutSafeExceptMaybeBarsRect; displayCutoutSafeExceptMaybeBars.set(displayCutoutSafe); - boolean clippedByDisplayCutout = false; + outFrames.isParentFrameClippedByDisplayCutout = false; if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS && !cutout.isEmpty()) { // Ensure that windows with a non-ALWAYS display cutout mode are laid out in // the cutout safe zone. @@ -158,7 +161,7 @@ public class WindowLayout { if (!attachedInParent && !floatingInScreenWindow) { mTempRect.set(outParentFrame); outParentFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars); - clippedByDisplayCutout = !mTempRect.equals(outParentFrame); + outFrames.isParentFrameClippedByDisplayCutout = !mTempRect.equals(outParentFrame); } outDisplayFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars); } @@ -287,9 +290,7 @@ public class WindowLayout { } if (DEBUG) Log.d(TAG, "computeWindowFrames " + attrs.getTitle() - + " outFrame=" + outFrame.toShortString() - + " outParentFrame=" + outParentFrame.toShortString() - + " outDisplayFrame=" + outDisplayFrame.toShortString() + + " outFrames=" + outFrames + " windowBounds=" + windowBounds.toShortString() + " attachedWindowFrame=" + (attachedWindowFrame != null ? attachedWindowFrame.toShortString() @@ -302,8 +303,6 @@ public class WindowLayout { + " attrs=" + attrs + " state=" + state + " requestedVisibilities=" + requestedVisibilities); - - return clippedByDisplayCutout; } public static void computeSurfaceSize(WindowManager.LayoutParams attrs, Rect maxBounds, diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index a270c9283ddc..ad151df05579 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -22,6 +22,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Region; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; @@ -217,9 +218,13 @@ public class WindowlessWindowManager implements IWindowSession { throw new IllegalArgumentException( "Invalid window token (never added or removed already)"); } + removeSurface(state.mSurfaceControl); + } + /** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */ + protected void removeSurface(SurfaceControl sc) { try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) { - t.remove(state.mSurfaceControl).apply(); + t.remove(sc).apply(); } } @@ -277,7 +282,7 @@ public class WindowlessWindowManager implements IWindowSession { int requestedWidth, int requestedHeight, int viewFlags, int flags, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) { final State state; synchronized (this) { state = mStateForWindow.get(window.asBinder()); @@ -354,7 +359,7 @@ public class WindowlessWindowManager implements IWindowSession { @Override public void finishDrawing(android.view.IWindow window, - android.view.SurfaceControl.Transaction postDrawTransaction) { + android.view.SurfaceControl.Transaction postDrawTransaction, int seqId) { synchronized (this) { final ResizeCompleteCallback c = mResizeCompletionForWindow.get(window.asBinder()); diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index a8cc114c4d69..3c5007b5b728 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -3121,17 +3121,19 @@ public final class AutofillManager { } /** - * If autofill suggestions for a dialog-style UI are available for {@code view}, shows a dialog - * allowing the user to select a suggestion and returns {@code true}. + * If autofill suggestions for a + * <a href="{@docRoot}reference/android/service/autofill/Dataset.html#FillDialogUI"> + * dialog-style UI</a> are available for {@code view}, shows a dialog allowing the user to + * select a suggestion and returns {@code true}. * <p> * The dialog may not be available if the autofill service does not support it, or if the * autofill request has not returned a response yet. * <p> - * It is recommended to call this method the first time a user focuses on an autofill-able form, - * and to avoid showing the input method if the dialog is shown. If this method returns - * {@code false}, you should then instead show the input method (assuming that is how the - * view normally handles the focus event). If the user re-focuses on the view, you should not - * call this method again so as to not disrupt usage of the input method. + * It is recommended apps to call this method the first time a user focuses on + * an autofill-able form, and to avoid showing the input method if the dialog is shown. If + * this method returns {@code false}, you should then instead show the input method (assuming + * that is how the view normally handles the focus event). If the user re-focuses on the view, + * you should not call this method again so as to not disrupt usage of the input method. * * @param view the view for which to show autofill suggestions. This is typically a view * receiving a focus event. The autofill suggestions shown will include content for 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/android/widget/TextView.java b/core/java/android/widget/TextView.java index b076d399d44a..3c8fcb978fbd 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -788,7 +788,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private Layout mLayout; private boolean mLocalesChanged = false; private int mTextSizeUnit = -1; - private LineBreakConfig mLineBreakConfig = new LineBreakConfig(); + private int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE; + private int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE; // This is used to reflect the current user preference for changing font weight and making text // more bold. @@ -1457,13 +1458,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; case com.android.internal.R.styleable.TextView_lineBreakStyle: - mLineBreakConfig.setLineBreakStyle( - a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE)); + mLineBreakStyle = a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE); break; case com.android.internal.R.styleable.TextView_lineBreakWordStyle: - mLineBreakConfig.setLineBreakWordStyle( - a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE)); + mLineBreakWordStyle = a.getInt(attr, + LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE); break; case com.android.internal.R.styleable.TextView_autoSizeTextType: @@ -4301,13 +4301,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @LineBreakConfig.LineBreakStyle int lineBreakStyle, @LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) { boolean updated = false; - if (isLineBreakStyleSpecified && mLineBreakConfig.getLineBreakStyle() != lineBreakStyle) { - mLineBreakConfig.setLineBreakStyle(lineBreakStyle); + if (isLineBreakStyleSpecified && mLineBreakStyle != lineBreakStyle) { + mLineBreakStyle = lineBreakStyle; updated = true; } - if (isLineBreakWordStyleSpecified - && mLineBreakConfig.getLineBreakWordStyle() != lineBreakWordStyle) { - mLineBreakConfig.setLineBreakWordStyle(lineBreakWordStyle); + if (isLineBreakWordStyleSpecified && mLineBreakWordStyle != lineBreakWordStyle) { + mLineBreakWordStyle = lineBreakWordStyle; updated = true; } if (updated && mLayout != null) { @@ -4871,50 +4870,72 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets line break configuration indicates which strategy needs to be used when calculating the - * text wrapping. - * <P> - * There are two types of line break rules that can be configured at the same time. One is - * line break style(lb) and the other is line break word style(lw). The line break style - * affects rule-based breaking. The line break word style affects dictionary-based breaking - * and provide phrase-based breaking opportunities. There are several types for the - * line break style: + * Set the line break style for text wrapping. + * + * The line break style to indicates the line break strategies can be used when + * calculating the text wrapping. The line break style affects rule-based breaking. It + * specifies the strictness of line-breaking rules. + * There are several types for the line break style: * {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE}, * {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and - * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. - * The type for the line break word style is - * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. - * The default values of the line break style and the line break word style are - * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and - * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE} respectively, indicating that no line - * breaking rules are specified. - * See <a href="https://drafts.csswg.org/css-text/#line-break-property"> + * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style + * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified. + * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property"> * the line-break property</a> * - * @param lineBreakConfig the line break config for text wrapping. + * @param lineBreakStyle the line break style for the text. */ - public void setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) { - Objects.requireNonNull(lineBreakConfig); - if (mLineBreakConfig.equals(lineBreakConfig)) { - return; + public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) { + if (mLineBreakStyle != lineBreakStyle) { + mLineBreakStyle = lineBreakStyle; + if (mLayout != null) { + nullLayouts(); + requestLayout(); + invalidate(); + } } - mLineBreakConfig.set(lineBreakConfig); - if (mLayout != null) { - nullLayouts(); - requestLayout(); - invalidate(); + } + + /** + * Set the line break word style for text wrapping. + * + * The line break word style affects dictionary-based breaking and provide phrase-based + * breaking opportunities. The type for the line break word style is + * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break + * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule + * is specified. + * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property"> + * the word-break property</a> + * + * @param lineBreakWordStyle the line break word style for the tet + */ + public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) { + if (mLineBreakWordStyle != lineBreakWordStyle) { + mLineBreakWordStyle = lineBreakWordStyle; + if (mLayout != null) { + nullLayouts(); + requestLayout(); + invalidate(); + } } } /** - * Get the current line break configuration for text wrapping. + * Get the current line break style for text wrapping. * - * @return the current line break configuration to be used for text wrapping. + * @return the current line break style to be used for text wrapping. */ - public @NonNull LineBreakConfig getLineBreakConfig() { - LineBreakConfig lbConfig = new LineBreakConfig(); - lbConfig.set(mLineBreakConfig); - return lbConfig; + public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() { + return mLineBreakStyle; + } + + /** + * Get the current line word break style for text wrapping. + * + * @return the current line break word style to be used for text wrapping. + */ + public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() { + return mLineBreakWordStyle; } /** @@ -4924,7 +4945,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see PrecomputedText */ public @NonNull PrecomputedText.Params getTextMetricsParams() { - return new PrecomputedText.Params(new TextPaint(mTextPaint), mLineBreakConfig, + return new PrecomputedText.Params(new TextPaint(mTextPaint), + LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle), getTextDirectionHeuristic(), mBreakStrategy, mHyphenationFrequency); } @@ -4941,13 +4963,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mTextDir = params.getTextDirection(); mBreakStrategy = params.getBreakStrategy(); mHyphenationFrequency = params.getHyphenationFrequency(); - if (params.getLineBreakConfig() != null) { - mLineBreakConfig.set(params.getLineBreakConfig()); - } else { - // Set default value if the line break config in the PrecomputedText.Params is null. - mLineBreakConfig.setLineBreakStyle(DEFAULT_LINE_BREAK_STYLE); - mLineBreakConfig.setLineBreakWordStyle(DEFAULT_LINE_BREAK_WORD_STYLE); - } + LineBreakConfig lineBreakConfig = params.getLineBreakConfig(); + mLineBreakStyle = lineBreakConfig.getLineBreakStyle(); + mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle(); if (mLayout != null) { nullLayouts(); requestLayout(); @@ -6486,7 +6504,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } final @PrecomputedText.Params.CheckResultUsableResult int checkResult = precomputed.getParams().checkResultUsable(getPaint(), mTextDir, mBreakStrategy, - mHyphenationFrequency, mLineBreakConfig); + mHyphenationFrequency, LineBreakConfig.getLineBreakConfig( + mLineBreakStyle, mLineBreakWordStyle)); switch (checkResult) { case PrecomputedText.Params.UNUSABLE: throw new IllegalArgumentException( @@ -9383,7 +9402,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setHyphenationFrequency(mHyphenationFrequency) .setJustificationMode(mJustificationMode) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE) - .setLineBreakConfig(mLineBreakConfig); + .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( + mLineBreakStyle, mLineBreakWordStyle)); if (shouldEllipsize) { builder.setEllipsize(mEllipsize) .setEllipsizedWidth(ellipsisWidth); @@ -9498,7 +9518,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setHyphenationFrequency(mHyphenationFrequency) .setJustificationMode(mJustificationMode) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE) - .setLineBreakConfig(mLineBreakConfig); + .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( + mLineBreakStyle, mLineBreakWordStyle)); if (shouldEllipsize) { builder.setEllipsize(effectiveEllipsize) .setEllipsizedWidth(ellipsisWidth); @@ -9866,7 +9887,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setJustificationMode(getJustificationMode()) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE) .setTextDirection(getTextDirectionHeuristic()) - .setLineBreakConfig(mLineBreakConfig); + .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( + mLineBreakStyle, mLineBreakWordStyle)); final StaticLayout layout = layoutBuilder.build(); diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java index acf9882e6658..5b915cc22ec5 100644 --- a/core/java/android/window/ClientWindowFrames.java +++ b/core/java/android/window/ClientWindowFrames.java @@ -27,47 +27,55 @@ import android.os.Parcelable; */ public class ClientWindowFrames implements Parcelable { /** The actual window bounds. */ - public final @NonNull Rect frame; + public final @NonNull Rect frame = new Rect(); /** * The container frame that is usually the same as display size. It may exclude the area of * insets if the window layout parameter has specified fit-insets-sides. */ - public final @NonNull Rect displayFrame; + public final @NonNull Rect displayFrame = new Rect(); + + /** + * The frame to be referenced while applying gravity and MATCH_PARENT. + */ + public final @NonNull Rect parentFrame = new Rect(); /** The background area while the window is resizing. */ - public final @NonNull Rect backdropFrame; + public final @NonNull Rect backdropFrame = new Rect(); + + public boolean isParentFrameClippedByDisplayCutout; public ClientWindowFrames() { - frame = new Rect(); - displayFrame = new Rect(); - backdropFrame = new Rect(); } public ClientWindowFrames(ClientWindowFrames other) { - frame = new Rect(other.frame); - displayFrame = new Rect(other.displayFrame); - backdropFrame = new Rect(other.backdropFrame); + frame.set(other.frame); + displayFrame.set(other.displayFrame); + parentFrame.set(other.parentFrame); + backdropFrame.set(other.backdropFrame); + isParentFrameClippedByDisplayCutout = other.isParentFrameClippedByDisplayCutout; } private ClientWindowFrames(Parcel in) { - frame = Rect.CREATOR.createFromParcel(in); - displayFrame = Rect.CREATOR.createFromParcel(in); - backdropFrame = Rect.CREATOR.createFromParcel(in); + readFromParcel(in); } /** Needed for AIDL out parameters. */ public void readFromParcel(Parcel in) { frame.readFromParcel(in); displayFrame.readFromParcel(in); + parentFrame.readFromParcel(in); backdropFrame.readFromParcel(in); + isParentFrameClippedByDisplayCutout = in.readBoolean(); } @Override public void writeToParcel(Parcel dest, int flags) { frame.writeToParcel(dest, flags); displayFrame.writeToParcel(dest, flags); + parentFrame.writeToParcel(dest, flags); backdropFrame.writeToParcel(dest, flags); + dest.writeBoolean(isParentFrameClippedByDisplayCutout); } @Override @@ -75,7 +83,9 @@ public class ClientWindowFrames implements Parcelable { final StringBuilder sb = new StringBuilder(32); return "ClientWindowFrames{frame=" + frame.toShortString(sb) + " display=" + displayFrame.toShortString(sb) - + " backdrop=" + backdropFrame.toShortString(sb) + "}"; + + " parentFrame=" + parentFrame.toShortString(sb) + + " backdrop=" + backdropFrame.toShortString(sb) + + " parentClippedByDisplayCutout=" + isParentFrameClippedByDisplayCutout + "}"; } @Override diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java index 3359a41369d7..1270d87e3a04 100644 --- a/core/java/android/window/DisplayWindowPolicyController.java +++ b/core/java/android/window/DisplayWindowPolicyController.java @@ -17,12 +17,14 @@ package android.window; import android.annotation.NonNull; +import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.util.ArraySet; import java.io.PrintWriter; import java.util.List; +import java.util.Set; /** * Abstract class to control the policies of the windows that can be displayed on the virtual @@ -46,6 +48,22 @@ public abstract class DisplayWindowPolicyController { private int mSystemWindowFlags; /** + * The set of windowing mode that are supported in this display. + * @see android.app.WindowConfiguration.WindowingMode + */ + private final Set<Integer> mSupportedWindowingModes = new ArraySet<>(); + + /** + * A controller to control the policies of the windows that can be displayed on the virtual + * display. + */ + public DisplayWindowPolicyController() { + synchronized (mSupportedWindowingModes) { + mSupportedWindowingModes.add(WindowConfiguration.WINDOWING_MODE_FULLSCREEN); + } + } + + /** * Returns {@code true} if the given window flags contain the flags that we're interested in. */ public final boolean isInterestedWindowFlags(int windowFlags, int systemWindowFlags) { @@ -62,9 +80,34 @@ public abstract class DisplayWindowPolicyController { } /** - * Returns {@code true} if the given activities can be displayed on this virtual display. + * Returns {@code true} if the given windowing mode is supported in this display. + */ + public final boolean isWindowingModeSupported( + @WindowConfiguration.WindowingMode int windowingMode) { + synchronized (mSupportedWindowingModes) { + return mSupportedWindowingModes.contains(windowingMode); + } + } + + /** + * Sets the windowing modes are supported in this display. + * + * @param supportedWindowingModes The set of + * {@link android.app.WindowConfiguration.WindowingMode}. + */ + public final void setSupportedWindowingModes(Set<Integer> supportedWindowingModes) { + synchronized (mSupportedWindowingModes) { + mSupportedWindowingModes.clear(); + mSupportedWindowingModes.addAll(supportedWindowingModes); + } + } + + /** + * Returns {@code true} if the given activities can be displayed on this virtual display and + * the windowing mode is supported. */ - public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities); + public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities, + @WindowConfiguration.WindowingMode int windowingMode); /** * Called when an Activity window is layouted with the new changes where contains the diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 5dbb551da681..d046cefee5f7 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -53,7 +53,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { private static final String TAG = "WindowOnBackDispatcher"; private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; private static final boolean IS_BACK_PREDICTABILITY_ENABLED = SystemProperties - .getInt(BACK_PREDICTABILITY_PROP, 0) > 0; + .getInt(BACK_PREDICTABILITY_PROP, 1) > 0; /** Convenience hashmap to quickly decide if a callback has been added. */ private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>(); diff --git a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java index 45555bf98071..dbbe4b9675d7 100644 --- a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java +++ b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java @@ -24,6 +24,7 @@ import android.view.Choreographer; * * @hide */ +// TODO(b/222698397): remove getSfInstance/this class usage and use vsyncId for transactions public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbackProvider { private final Choreographer mChoreographer; diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java index 9e07f973b3c4..cb162674eb16 100644 --- a/core/java/com/android/internal/infra/ServiceConnector.java +++ b/core/java/com/android/internal/infra/ServiceConnector.java @@ -31,6 +31,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; +import android.util.Slog; import java.io.PrintWriter; import java.util.ArrayDeque; @@ -562,10 +563,21 @@ public interface ServiceConnector<I extends IInterface> { void unbindJobThread() { cancelTimeout(); I service = mService; + // TODO(b/224695239): This is actually checking wasConnected. Rename and/or fix + // implementation based on what this should actually be checking. At least the first + // check for calling unbind is the correct behavior, though. boolean wasBound = service != null; + if (wasBound || mBinding) { + try { + mContext.unbindService(mServiceConnection); + } catch (IllegalArgumentException e) { // TODO(b/224697137): Fix the race condition + // that requires catching this (crashes if + // service isn't currently bound). + Slog.e(LOG_TAG, "Failed to unbind: " + e); + } + } if (wasBound) { dispatchOnServiceConnectionStatusChanged(service, false); - mContext.unbindService(mServiceConnection); service.asBinder().unlinkToDeath(this, 0); mService = null; } diff --git a/core/java/com/android/internal/os/AudioPowerCalculator.java b/core/java/com/android/internal/os/AudioPowerCalculator.java index f9310b0c28d9..ebf0ca263a62 100644 --- a/core/java/com/android/internal/os/AudioPowerCalculator.java +++ b/core/java/com/android/internal/os/AudioPowerCalculator.java @@ -78,7 +78,9 @@ public class AudioPowerCalculator extends PowerCalculator { final double powerMah = mPowerEstimator.calculatePower(durationMs); app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_AUDIO, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_AUDIO, powerMah); - total.durationMs += durationMs; - total.powerMah += powerMah; + if (!app.isVirtualUid()) { + total.durationMs += durationMs; + total.powerMah += powerMah; + } } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 70b96392b0e5..3b46f627265b 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -166,7 +166,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - static final int VERSION = 206; + static final int VERSION = 207; // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -546,9 +546,9 @@ public class BatteryStatsImpl extends BatteryStats { final LongArrayMultiStateCounter onBatteryScreenOffCounter = u.getProcStateScreenOffTimeCounter().getCounter(); - if (uid == parentUid) { - mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, timestampMs); - mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, + if (uid == parentUid || Process.isSdkSandboxUid(uid)) { + mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, timestampMs); + mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter, timestampMs); } else { Uid.ChildUid childUid = u.getChildUid(uid); @@ -964,6 +964,16 @@ public class BatteryStatsImpl extends BatteryStats { * Timers for each combination of frequency range and signal strength. */ public final StopwatchTimer[][] perStateTimers; + /** + * Counters tracking the time (in milliseconds) spent transmitting data in a given state. + */ + @Nullable + private LongSamplingCounter[][] mPerStateTxDurationMs = null; + /** + * Counters tracking the time (in milliseconds) spent receiving data in at given frequency. + */ + @Nullable + private LongSamplingCounter[] mPerFrequencyRxDurationMs = null; RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) { perStateTimers = @@ -1024,15 +1034,198 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * Reset display timers. + * Returns the duration in milliseconds spent in a given state since the last mark. + */ + public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange, + int signalStrength, long elapsedRealtimeMs) { + return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked( + elapsedRealtimeMs * 1000) / 1000; + } + + /** + * Set mark for all timers. + */ + public void setMark(long elapsedRealtimeMs) { + final int size = perStateTimers.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) { + perStateTimers[i][j].setMark(elapsedRealtimeMs); + } + } + } + + /** + * Returns numbers of frequencies tracked for this RAT. + */ + public int getFrequencyRangeCount() { + return perStateTimers.length; + } + + /** + * Add TX time for a given state. + */ + public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange, + int signalStrength, long durationMs) { + getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs); + } + + /** + * Add TX time for a given frequency. + */ + public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange, + long durationMs) { + getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs); + } + + /** + * Reset radio access technology timers and counts. */ public void reset(long elapsedRealtimeUs) { final int size = perStateTimers.length; for (int i = 0; i < size; i++) { for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) { perStateTimers[i][j].reset(false, elapsedRealtimeUs); + if (mPerStateTxDurationMs == null) continue; + mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs); + } + if (mPerFrequencyRxDurationMs == null) continue; + mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs); + } + } + + /** + * Write data to summary parcel + */ + public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) { + final int freqCount = perStateTimers.length; + out.writeInt(freqCount); + out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS); + for (int i = 0; i < freqCount; i++) { + for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) { + perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs); + } + } + + if (mPerStateTxDurationMs == null) { + out.writeInt(0); + } else { + out.writeInt(1); + for (int i = 0; i < freqCount; i++) { + for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) { + mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out); + } + } + } + + if (mPerFrequencyRxDurationMs == null) { + out.writeInt(0); + } else { + out.writeInt(1); + for (int i = 0; i < freqCount; i++) { + mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out); + } + } + } + + /** + * Read data from summary parcel + */ + public void readSummaryFromParcel(Parcel in) { + final int oldFreqCount = in.readInt(); + final int oldSignalStrengthCount = in.readInt(); + final int currFreqCount = perStateTimers.length; + final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; + + for (int freq = 0; freq < oldFreqCount; freq++) { + for (int strength = 0; strength < oldSignalStrengthCount; strength++) { + if (freq >= currFreqCount || strength >= currSignalStrengthCount) { + // Mismatch with the summary parcel. Consume the data but don't use it. + final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null, + new TimeBase()); + // Consume perStateTimers data. + temp.readSummaryFromParcelLocked(in); + } else { + perStateTimers[freq][strength].readSummaryFromParcelLocked(in); + } + } + } + + if (in.readInt() == 1) { + for (int freq = 0; freq < oldFreqCount; freq++) { + for (int strength = 0; strength < oldSignalStrengthCount; strength++) { + if (freq >= currFreqCount || strength >= currSignalStrengthCount) { + // Mismatch with the summary parcel. Consume the data but don't use it. + final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null, + new TimeBase()); + // Consume mPerStateTxDurationMs data. + temp.readSummaryFromParcelLocked(in); + } + getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in); + } + } + } + + if (in.readInt() == 1) { + for (int freq = 0; freq < oldFreqCount; freq++) { + if (freq >= currFreqCount) { + // Mismatch with the summary parcel. Consume the data but don't use it. + final StopwatchTimer + temp = new StopwatchTimer(null, null, -1, null, new TimeBase()); + // Consume mPerFrequencyRxDurationMs data. + temp.readSummaryFromParcelLocked(in); + continue; + } + getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in); + } + } + } + + private LongSamplingCounter getTxDurationCounter( + @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) { + if (mPerStateTxDurationMs == null) { + if (!make) return null; + + final int freqCount = getFrequencyRangeCount(); + final int signalStrengthCount = perStateTimers[0].length; + final TimeBase timeBase = perStateTimers[0][0].mTimeBase; + mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount]; + for (int freq = 0; freq < freqCount; freq++) { + for (int strength = 0; strength < signalStrengthCount; strength++) { + mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase); + } + } + } + if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) { + Slog.w(TAG, "Unexpected frequency range (" + frequencyRange + + ") requested in getTxDurationCounter"); + return null; + } + if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) { + Slog.w(TAG, "Unexpected signal strength (" + signalStrength + + ") requested in getTxDurationCounter"); + return null; + } + return mPerStateTxDurationMs[frequencyRange][signalStrength]; + } + + private LongSamplingCounter getRxDurationCounter( + @ServiceState.FrequencyRange int frequencyRange, boolean make) { + if (mPerFrequencyRxDurationMs == null) { + if (!make) return null; + + final int freqCount = getFrequencyRangeCount(); + final TimeBase timeBase = perStateTimers[0][0].mTimeBase; + mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount]; + for (int freq = 0; freq < freqCount; freq++) { + mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase); } } + if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) { + Slog.w(TAG, "Unexpected frequency range (" + frequencyRange + + ") requested in getRxDurationCounter"); + return null; + } + return mPerFrequencyRxDurationMs[frequencyRange]; } } @@ -1929,20 +2122,28 @@ public class BatteryStatsImpl extends BatteryStats { private final TimeBase mTimeBase; private final LongMultiStateCounter mCounter; - private TimeMultiStateCounter(TimeBase timeBase, Parcel in, long timestampMs) { - mTimeBase = timeBase; - mCounter = LongMultiStateCounter.CREATOR.createFromParcel(in); - mCounter.setEnabled(mTimeBase.isRunning(), timestampMs); - timeBase.add(this); + private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) { + this(timeBase, new LongMultiStateCounter(stateCount), timestampMs); } - private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) { + private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, + long timestampMs) { mTimeBase = timeBase; - mCounter = new LongMultiStateCounter(stateCount); + mCounter = counter; mCounter.setEnabled(mTimeBase.isRunning(), timestampMs); timeBase.add(this); } + @Nullable + private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase, + int stateCount, long timestampMs) { + LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in); + if (counter.getStateCount() != stateCount) { + return null; + } + return new TimeMultiStateCounter(timeBase, counter, timestampMs); + } + private void writeToParcel(Parcel out) { mCounter.writeToParcel(out, 0); } @@ -3510,11 +3711,8 @@ public class BatteryStatsImpl extends BatteryStats { private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) { if (in.readBoolean()) { - final TimeMultiStateCounter counter = - new TimeMultiStateCounter(timeBase, in, mClock.elapsedRealtime()); - if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) { - return counter; - } + return TimeMultiStateCounter.readFromParcel(in, timeBase, + BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime()); } return null; } @@ -3537,9 +3735,10 @@ public class BatteryStatsImpl extends BatteryStats { // invalid. TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters]; for (int i = 0; i < numCounters; i++) { - final TimeMultiStateCounter counter = - new TimeMultiStateCounter(timeBase, in, mClock.elapsedRealtime()); - if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) { + final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in, + timeBase, BatteryConsumer.PROCESS_STATE_COUNT, + mClock.elapsedRealtime()); + if (counter != null) { counters[i] = counter; } else { valid = false; @@ -4560,7 +4759,10 @@ public class BatteryStatsImpl extends BatteryStats { mIsolatedUidRefCounts.put(uid, refCount + 1); } - public int mapUid(int uid) { + private int mapUid(int uid) { + if (Process.isSdkSandboxUid(uid)) { + return Process.getAppUidForSdkSandboxUid(uid); + } int isolated = mIsolatedUids.get(uid, -1); return isolated > 0 ? isolated : uid; } @@ -4656,16 +4858,18 @@ public class BatteryStatsImpl extends BatteryStats { long elapsedRealtimeMs, long uptimeMs) { int parentUid = mapUid(uid); if (uid != parentUid) { - // Isolated UIDs process state is already rolled up into parent, so no need to track - // Otherwise the parent's process state will get downgraded incorrectly - return; + if (Process.isIsolated(uid)) { + // Isolated UIDs process state is already rolled up into parent, so no need to track + // Otherwise the parent's process state will get downgraded incorrectly + return; + } } // TODO(b/155216561): It is possible for isolated uids to be in a higher // state than its parent uid. We should track the highest state within the union of host // and isolated uids rather than only the parent uid. FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid, ActivityManager.processStateAmToProto(state)); - getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs) .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs); } @@ -7995,6 +8199,32 @@ public class BatteryStatsImpl extends BatteryStats { elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000; } + @Override + public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat, + @ServiceState.FrequencyRange int frequencyRange, int signalStrength, + long elapsedRealtimeMs) { + final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat]; + if (stats == null) return DURATION_UNAVAILABLE; + + final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange, + signalStrength, false); + if (counter == null) return DURATION_UNAVAILABLE; + + return counter.getCountLocked(STATS_SINCE_CHARGED); + } + + @Override + public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat, + @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) { + final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat]; + if (stats == null) return DURATION_UNAVAILABLE; + + final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false); + if (counter == null) return DURATION_UNAVAILABLE; + + return counter.getCountLocked(STATS_SINCE_CHARGED); + } + @UnsupportedAppUsage @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) { return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which); @@ -10739,11 +10969,9 @@ public class BatteryStatsImpl extends BatteryStats { = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in); } if (in.readBoolean()) { - final TimeMultiStateCounter counter = - new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, in, timestampMs); - if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) { - mMobileRadioActiveTime = counter; - } + mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in, + mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, + timestampMs); } mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in); @@ -10789,11 +11017,9 @@ public class BatteryStatsImpl extends BatteryStats { int stateCount = in.readInt(); if (stateCount != 0) { - final TimeMultiStateCounter counter = new TimeMultiStateCounter( - mBsi.mOnBatteryTimeBase, in, timestampMs); - if (stateCount == BatteryConsumer.PROCESS_STATE_COUNT) { - mCpuActiveTimeMs = counter; - } + mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in, + mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, + timestampMs); } mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in); @@ -13477,6 +13703,67 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mTmpRailStats.resetCellularTotalEnergyUsed(); } + + // Proportionally smear Rx and Tx times across each RAt + final int levelCount = CellSignalStrength.getNumSignalStrengthLevels(); + long[] perSignalStrengthActiveTimeMs = new long[levelCount]; + long totalActiveTimeMs = 0; + + for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) { + final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat]; + if (ratStats == null) continue; + + final int freqCount = ratStats.getFrequencyRangeCount(); + for (int freq = 0; freq < freqCount; freq++) { + for (int level = 0; level < levelCount; level++) { + final long durationMs = ratStats.getTimeSinceMark(freq, level, + elapsedRealtimeMs); + perSignalStrengthActiveTimeMs[level] += durationMs; + totalActiveTimeMs += durationMs; + } + } + } + + if (totalActiveTimeMs != 0) { + // Smear the provided Tx/Rx durations across each RAT, frequency, and signal + // strength. + for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) { + final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat]; + if (ratStats == null) continue; + + final int freqCount = ratStats.getFrequencyRangeCount(); + for (int freq = 0; freq < freqCount; freq++) { + long frequencyDurationMs = 0; + for (int level = 0; level < levelCount; level++) { + final long durationMs = ratStats.getTimeSinceMark(freq, level, + elapsedRealtimeMs); + final long totalLvlDurationMs = + perSignalStrengthActiveTimeMs[level]; + if (totalLvlDurationMs == 0) continue; + final long totalTxLvlDurations = + deltaInfo.getTransmitDurationMillisAtPowerLevel(level); + // Smear HAL provided Tx power level duration based on active modem + // duration in a given state. (Add totalLvlDurationMs / 2 before + // the integer division with totalLvlDurationMs for rounding.) + final long proportionalTxDurationMs = + (durationMs * totalTxLvlDurations + + (totalLvlDurationMs / 2)) / totalLvlDurationMs; + ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs); + frequencyDurationMs += durationMs; + } + final long totalRxDuration = deltaInfo.getReceiveTimeMillis(); + // Smear HAL provided Rx power duration based on active modem + // duration in a given state. (Add totalActiveTimeMs / 2 before the + // integer division with totalActiveTimeMs for rounding.) + final long proportionalRxDurationMs = + (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs + / 2)) / totalActiveTimeMs; + ratStats.incrementRxDuration(freq, proportionalRxDurationMs); + } + + ratStats.setMark(elapsedRealtimeMs); + } + } } long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); @@ -15970,6 +16257,9 @@ public class BatteryStatsImpl extends BatteryStats { public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { Uid u = mUidStats.get(uid); if (u == null) { + if (Process.isSdkSandboxUid(uid)) { + Log.wtf(TAG, "Tracking an SDK Sandbox UID"); + } u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs); mUidStats.put(uid, u); } @@ -16879,14 +17169,18 @@ public class BatteryStatsImpl extends BatteryStats { mNextMaxDailyDeadlineMs = in.readLong(); mBatteryTimeToFullSeconds = in.readLong(); - mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in); - - /** - * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled - * later when {@link #initMeasuredEnergyStatsLocked} is called. - */ - mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( - mMeasuredEnergyStatsConfig, in); + final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in); + final MeasuredEnergyStats measuredEnergyStats = + MeasuredEnergyStats.createAndReadSummaryFromParcel(mMeasuredEnergyStatsConfig, in); + if (config != null && Arrays.equals(config.getStateNames(), + getBatteryConsumerProcessStateNames())) { + /** + * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled + * later when {@link #initMeasuredEnergyStatsLocked} is called. + */ + mMeasuredEnergyStatsConfig = config; + mGlobalMeasuredEnergyStats = measuredEnergyStats; + } mStartCount++; @@ -16918,6 +17212,13 @@ public class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in); mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in); } + + final int numRat = in.readInt(); + for (int i = 0; i < numRat; i++) { + if (in.readInt() == 0) continue; + getRatBatteryStatsLocked(i).readSummaryFromParcel(in); + } + mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; mMobileRadioActiveTimer.readSummaryFromParcelLocked(in); mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in); @@ -16978,7 +17279,6 @@ public class BatteryStatsImpl extends BatteryStats { getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in); } } - int NKW = in.readInt(); if (NKW > 10000) { throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW); @@ -17106,11 +17406,9 @@ public class BatteryStatsImpl extends BatteryStats { u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in); } if (in.readBoolean()) { - TimeMultiStateCounter counter = new TimeMultiStateCounter( - mOnBatteryTimeBase, in, elapsedRealtimeMs); - if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) { - u.mMobileRadioActiveTime = counter; - } + u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in, + mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, + elapsedRealtimeMs); } u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in); } @@ -17160,11 +17458,9 @@ public class BatteryStatsImpl extends BatteryStats { int stateCount = in.readInt(); if (stateCount != 0) { - final TimeMultiStateCounter counter = new TimeMultiStateCounter( - mOnBatteryTimeBase, in, mClock.elapsedRealtime()); - if (stateCount == BatteryConsumer.PROCESS_STATE_COUNT) { - u.mCpuActiveTimeMs = counter; - } + u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in, + mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, + mClock.elapsedRealtime()); } u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in); @@ -17423,6 +17719,17 @@ public class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out); mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out); } + final int numRat = mPerRatBatteryStats.length; + out.writeInt(numRat); + for (int i = 0; i < numRat; i++) { + final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i]; + if (ratStat == null) { + out.writeInt(0); + continue; + } + out.writeInt(1); + ratStat.writeSummaryToParcel(out, nowRealtime); + } mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime); mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime); mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out); @@ -17999,9 +18306,15 @@ public class BatteryStatsImpl extends BatteryStats { mLastWriteTimeMs = in.readLong(); mBatteryTimeToFullSeconds = in.readLong(); - mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in); - mGlobalMeasuredEnergyStats = + + final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in); + final MeasuredEnergyStats measuredEnergyStats = MeasuredEnergyStats.createFromParcel(mMeasuredEnergyStatsConfig, in); + if (config != null && Arrays.equals(config.getStateNames(), + getBatteryConsumerProcessStateNames())) { + mMeasuredEnergyStatsConfig = config; + mGlobalMeasuredEnergyStats = measuredEnergyStats; + } mRpmStats.clear(); int NRPMS = in.readInt(); diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index a1c1917fd83e..81c6ee71e060 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -22,6 +22,7 @@ import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.Parcel; +import android.os.Process; import android.os.SystemClock; import android.os.UidBatteryConsumer; import android.util.Log; @@ -162,6 +163,8 @@ public class BatteryUsageStatsProvider { final boolean includeProcessStateData = ((query.getFlags() & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0) && mStats.isProcessStateDataAvailable(); + final boolean includeVirtualUids = ((query.getFlags() + & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0); final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder( mStats.getCustomEnergyConsumerNames(), includePowerModels, @@ -174,6 +177,10 @@ public class BatteryUsageStatsProvider { SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats(); for (int i = uidStats.size() - 1; i >= 0; i--) { final BatteryStats.Uid uid = uidStats.valueAt(i); + if (!includeVirtualUids && uid.getUid() == Process.SDK_SANDBOX_VIRTUAL_UID) { + continue; + } + batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uid) .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, getProcessBackgroundTimeMs(uid, realtimeUs)) diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java index 2ebf689e2c7f..e52c8a3a3efb 100644 --- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java +++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java @@ -139,8 +139,10 @@ public class BluetoothPowerCalculator extends PowerCalculator { BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.powerMah, powerModel); - powerAndDuration.totalDurationMs += powerAndDuration.durationMs; - powerAndDuration.totalPowerMah += powerAndDuration.powerMah; + if (!app.isVirtualUid()) { + powerAndDuration.totalDurationMs += powerAndDuration.durationMs; + powerAndDuration.totalPowerMah += powerAndDuration.powerMah; + } if (query.isProcessStateDataNeeded() && powerAndDuration.keys != null) { for (int j = 0; j < powerAndDuration.keys.length; j++) { diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java index 1fc2baf040b6..8704e936c747 100644 --- a/core/java/com/android/internal/os/CpuPowerCalculator.java +++ b/core/java/com/android/internal/os/CpuPowerCalculator.java @@ -117,7 +117,9 @@ public class CpuPowerCalculator extends PowerCalculator { } } calculateApp(app, app.getBatteryStatsUid(), query, result, keys); - totalPowerMah += result.powerMah; + if (!app.isVirtualUid()) { + totalPowerMah += result.powerMah; + } } final long consumptionUC = batteryStats.getCpuMeasuredBatteryConsumptionUC(); diff --git a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java index cbbb52621111..0853bd801137 100644 --- a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java +++ b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java @@ -96,7 +96,9 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator { app.setConsumedPowerForCustomComponent( BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i, customMeasuredPowerMah[i]); - newTotalPowerMah[i] += customMeasuredPowerMah[i]; + if (!app.isVirtualUid()) { + newTotalPowerMah[i] += customMeasuredPowerMah[i]; + } } } return newTotalPowerMah; diff --git a/core/java/com/android/internal/os/GnssPowerCalculator.java b/core/java/com/android/internal/os/GnssPowerCalculator.java index 0f783062f3e7..070783a04105 100644 --- a/core/java/com/android/internal/os/GnssPowerCalculator.java +++ b/core/java/com/android/internal/os/GnssPowerCalculator.java @@ -58,8 +58,11 @@ public class GnssPowerCalculator extends PowerCalculator { final long consumptionUC = app.getBatteryStatsUid().getGnssMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(consumptionUC, query); - appsPowerMah += calculateApp(app, app.getBatteryStatsUid(), powerModel, + final double powerMah = calculateApp(app, app.getBatteryStatsUid(), powerModel, rawRealtimeUs, averageGnssPowerMa, consumptionUC); + if (!app.isVirtualUid()) { + appsPowerMah += powerMah; + } } final long consumptionUC = batteryStats.getGnssMeasuredBatteryConsumptionUC(); diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java index f4624de289be..d0df45c9af65 100644 --- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java +++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java @@ -136,12 +136,14 @@ public class MobileRadioPowerCalculator extends PowerCalculator { PowerAndDuration total, BatteryUsageStatsQuery query, BatteryConsumer.Key[] keys) { final long radioActiveDurationMs = calculateDuration(u, BatteryStats.STATS_SINCE_CHARGED); - total.totalAppDurationMs += radioActiveDurationMs; - final long consumptionUC = u.getMobileRadioMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(consumptionUC, query); final double powerMah = calculatePower(u, powerModel, radioActiveDurationMs, consumptionUC); - total.totalAppPowerMah += powerMah; + + if (!app.isVirtualUid()) { + total.totalAppDurationMs += radioActiveDurationMs; + total.totalAppPowerMah += powerMah; + } app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, radioActiveDurationMs) diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java index 67d3d6e7bede..5ca1a857fbcd 100644 --- a/core/java/com/android/internal/os/ScreenPowerCalculator.java +++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java @@ -96,8 +96,10 @@ public class ScreenPowerCalculator extends PowerCalculator { appPowerAndDuration.durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, appPowerAndDuration.powerMah, powerModel); - totalAppPower += appPowerAndDuration.powerMah; - totalAppDuration += appPowerAndDuration.durationMs; + if (!app.isVirtualUid()) { + totalAppPower += appPowerAndDuration.powerMah; + totalAppDuration += appPowerAndDuration.durationMs; + } } break; case BatteryConsumer.POWER_MODEL_POWER_PROFILE: @@ -192,10 +194,13 @@ public class ScreenPowerCalculator extends PowerCalculator { long totalActivityTimeMs = 0; final SparseLongArray activityTimeArray = new SparseLongArray(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { - final BatteryStats.Uid uid = uidBatteryConsumerBuilders.valueAt(i).getBatteryStatsUid(); + final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); + final BatteryStats.Uid uid = app.getBatteryStatsUid(); final long timeMs = getProcessForegroundTimeMs(uid, rawRealtimeUs); activityTimeArray.put(uid.getUid(), timeMs); - totalActivityTimeMs += timeMs; + if (!app.isVirtualUid()) { + totalActivityTimeMs += timeMs; + } } if (totalActivityTimeMs >= MIN_ACTIVE_TIME_FOR_SMEARING) { diff --git a/core/java/com/android/internal/os/SensorPowerCalculator.java b/core/java/com/android/internal/os/SensorPowerCalculator.java index 4a9c91d14c4c..573692ea63f3 100644 --- a/core/java/com/android/internal/os/SensorPowerCalculator.java +++ b/core/java/com/android/internal/os/SensorPowerCalculator.java @@ -51,7 +51,9 @@ public class SensorPowerCalculator extends PowerCalculator { builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); - appsPowerMah += calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs); + if (!app.isVirtualUid()) { + appsPowerMah += calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs); + } } builder.getAggregateBatteryConsumerBuilder( diff --git a/core/java/com/android/internal/os/UserPowerCalculator.java b/core/java/com/android/internal/os/UserPowerCalculator.java index 22cff6e2435a..79e3a195dc82 100644 --- a/core/java/com/android/internal/os/UserPowerCalculator.java +++ b/core/java/com/android/internal/os/UserPowerCalculator.java @@ -49,7 +49,11 @@ public class UserPowerCalculator extends PowerCalculator { builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { - UidBatteryConsumer.Builder uidBuilder = uidBatteryConsumerBuilders.valueAt(i); + final UidBatteryConsumer.Builder uidBuilder = uidBatteryConsumerBuilders.valueAt(i); + if (uidBuilder.isVirtualUid()) { + continue; + } + final int uid = uidBuilder.getUid(); if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) { continue; diff --git a/core/java/com/android/internal/os/VideoPowerCalculator.java b/core/java/com/android/internal/os/VideoPowerCalculator.java index a222bcb4dfbf..2daf15eb14a6 100644 --- a/core/java/com/android/internal/os/VideoPowerCalculator.java +++ b/core/java/com/android/internal/os/VideoPowerCalculator.java @@ -75,7 +75,9 @@ public class VideoPowerCalculator extends PowerCalculator { final double powerMah = mPowerEstimator.calculatePower(durationMs); app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_VIDEO, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_VIDEO, powerMah); - total.durationMs += durationMs; - total.powerMah += powerMah; + if (!app.isVirtualUid()) { + total.durationMs += durationMs; + total.powerMah += powerMah; + } } } diff --git a/core/java/com/android/internal/os/WakelockPowerCalculator.java b/core/java/com/android/internal/os/WakelockPowerCalculator.java index 0251e1ccc885..3ae7113faf71 100644 --- a/core/java/com/android/internal/os/WakelockPowerCalculator.java +++ b/core/java/com/android/internal/os/WakelockPowerCalculator.java @@ -62,8 +62,10 @@ public class WakelockPowerCalculator extends PowerCalculator { BatteryStats.STATS_SINCE_CHARGED); app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WAKELOCK, result.durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_WAKELOCK, result.powerMah); - totalAppDurationMs += result.durationMs; - appPowerMah += result.powerMah; + if (!app.isVirtualUid()) { + totalAppDurationMs += result.durationMs; + appPowerMah += result.powerMah; + } if (app.getUid() == Process.ROOT_UID) { osBatteryConsumer = app; diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java index 8c3fb86331b2..2181821dd55a 100644 --- a/core/java/com/android/internal/os/WifiPowerCalculator.java +++ b/core/java/com/android/internal/os/WifiPowerCalculator.java @@ -111,9 +111,10 @@ public class WifiPowerCalculator extends PowerCalculator { calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), powerModel, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED, batteryStats.hasWifiActivityReporting(), consumptionUC); - - totalAppDurationMs += powerDurationAndTraffic.durationMs; - totalAppPowerMah += powerDurationAndTraffic.powerMah; + if (!app.isVirtualUid()) { + totalAppDurationMs += powerDurationAndTraffic.durationMs; + totalAppPowerMah += powerDurationAndTraffic.powerMah; + } app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI, powerDurationAndTraffic.durationMs); 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/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java index 7262e846d9b0..7fb8696a217d 100644 --- a/core/java/com/android/internal/power/MeasuredEnergyStats.java +++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java @@ -194,6 +194,7 @@ public class MeasuredEnergyStats { return mSupportedMultiStateBuckets[index]; } + @NonNull public String[] getStateNames() { return mStateNames; } @@ -321,6 +322,10 @@ public class MeasuredEnergyStats { LongMultiStateCounter multiStateCounter = null; if (in.readBoolean()) { multiStateCounter = LongMultiStateCounter.CREATOR.createFromParcel(in); + if (mConfig == null + || multiStateCounter.getStateCount() != mConfig.getStateNames().length) { + multiStateCounter = null; + } } if (index < mAccumulatedChargeMicroCoulomb.length) { diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index d629d66d1c31..089179dbba27 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -297,6 +297,11 @@ oneway interface IStatusBar */ void runGcForTest(); + /** + * Send a request to SystemUI to put a given active tile in listening state + */ + void requestTileServiceListeningState(in ComponentName componentName); + void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback); void cancelRequestAddTile(in String packageName); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 1d60c501a88b..2ee5e797b4ab 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -91,7 +91,7 @@ interface IStatusBarService void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, boolean isBubbleSuppressed); void hideCurrentInputMethodForBubbles(); void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName); - void clearInlineReplyUriPermissions(String key); + oneway void clearInlineReplyUriPermissions(String key); void onNotificationFeedbackReceived(String key, in Bundle feedback); void onGlobalActionsShown(); @@ -171,6 +171,11 @@ interface IStatusBarService */ void suppressAmbientDisplay(boolean suppress); + /** + * Send a request to SystemUI to put a given active tile in listening state + */ + void requestTileServiceListeningState(in ComponentName componentName, int userId); + void requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback); void cancelRequestAddTile(in String packageName); diff --git a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl b/core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl index 6ca8cecba3c8..0c8e73fb2b67 100644 --- a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl +++ b/core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl @@ -16,7 +16,8 @@ package com.android.internal.telephony; -oneway interface ICarrierPrivilegesListener { +oneway interface ICarrierPrivilegesCallback { void onCarrierPrivilegesChanged( in List<String> privilegedPackageNames, in int[] privilegedUids); + void onCarrierServiceChanged(in String carrierServicePackageName, in int carrierServiceUid); } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 9712d7e38a4b..c7fa757ac0b7 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -32,7 +32,7 @@ import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.emergency.EmergencyNumber; -import com.android.internal.telephony.ICarrierPrivilegesListener; +import com.android.internal.telephony.ICarrierPrivilegesCallback; import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener; @@ -102,9 +102,11 @@ interface ITelephonyRegistry { void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId, in List<LinkCapacityEstimate> linkCapacityEstimateList); - void addCarrierPrivilegesListener( - int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId); - void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg); + void addCarrierPrivilegesCallback( + int phoneId, ICarrierPrivilegesCallback callback, String pkg, String featureId); + void removeCarrierPrivilegesCallback(ICarrierPrivilegesCallback callback, String pkg); void notifyCarrierPrivilegesChanged( int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids); + void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid); + } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 6673f6781ef8..842d72a226b2 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -51,10 +51,10 @@ public class BaseIWindow extends IWindow.Stub { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId) { if (reportDraw) { try { - mSession.finishDrawing(this, null /* postDrawTransaction */); + mSession.finishDrawing(this, null /* postDrawTransaction */, seqId); } catch (RemoteException e) { } } diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 5fa4a652e176..4706affa3541 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -66,7 +66,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -76,8 +75,6 @@ import java.util.function.Consumer; public class ConversationLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -150,7 +147,7 @@ public class ConversationLayout extends FrameLayout private Icon mShortcutIcon; private View mAppNameDivider; private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this); - private ArrayList<MessagingGroup> mToRecycle = new ArrayList<>(); + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public ConversationLayout(@NonNull Context context) { super(context); @@ -463,8 +460,12 @@ public class ConversationLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -475,8 +476,8 @@ public class ConversationLayout extends FrameLayout updateConversationLayout(); // Recycle everything at the end of the update, now that we know it's no longer needed. - for (MessagingGroup group : mToRecycle) { - group.recycle(); + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); } mToRecycle.clear(); } diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 851e8e0f3269..3494c9e05b4a 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -53,7 +53,6 @@ interface ILockSettings { VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, int userId, int flags); VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId); void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle); - boolean checkVoldPassword(int userId); int getCredentialType(int userId); byte[] getHashFactor(in LockscreenCredential currentCredential, int userId); void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in LockscreenCredential managedUserPassword); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 82ae42441032..a94b30707604 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -526,20 +526,6 @@ public class LockPatternUtils { } /** - * Check to see if vold already has the password. - * Note that this also clears vold's copy of the password. - * @return Whether the vold password matches or not. - */ - public boolean checkVoldPassword(int userId) { - try { - return getLockSettings().checkVoldPassword(userId); - } catch (RemoteException re) { - Log.e(TAG, "failed to check vold password", re); - return false; - } - } - - /** * Returns the password history hash factor, needed to check new password against password * history with {@link #checkPasswordHistory(byte[], byte[], int)} */ @@ -808,7 +794,7 @@ public class LockPatternUtils { */ public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, LockscreenCredential profilePassword) { - if (!isCredentialSharedWithParent(userHandle)) { + if (!isCredentialSharableWithParent(userHandle)) { return; } try { @@ -824,7 +810,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 +835,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(); } /** @@ -1135,7 +1121,7 @@ public class LockPatternUtils { public List<ComponentName> getEnabledTrustAgents(int userId) { String serialized = getString(ENABLED_TRUST_AGENTS, userId); if (TextUtils.isEmpty(serialized)) { - return null; + return new ArrayList<ComponentName>(); } String[] split = serialized.split(","); ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length); diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index 9e06e33b79b5..146cb3fadaac 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -262,7 +262,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return createdGroup; } - public void removeMessage(MessagingMessage messagingMessage) { + public void removeMessage(MessagingMessage messagingMessage, + ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { View view = messagingMessage.getView(); boolean wasShown = view.isShown(); ViewGroup messageParent = (ViewGroup) view.getParent(); @@ -270,15 +271,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return; } messageParent.removeView(view); - Runnable recycleRunnable = () -> { - messageParent.removeTransientView(view); - messagingMessage.recycle(); - }; if (wasShown && !MessagingLinearLayout.isGone(view)) { messageParent.addTransientView(view, 0); - performRemoveAnimation(view, recycleRunnable); + performRemoveAnimation(view, () -> { + messageParent.removeTransientView(view); + messagingMessage.recycle(); + }); } else { - recycleRunnable.run(); + toRecycle.add(messagingMessage); } } diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index 21ca196886ab..9ac6ef77bc07 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -51,7 +51,6 @@ import com.android.internal.util.ContrastColorUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -62,8 +61,6 @@ public class MessagingLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { private static final float COLOR_SHIFT_AMOUNT = 60; - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -89,6 +86,7 @@ public class MessagingLayout extends FrameLayout private boolean mIsCollapsed; private ImageResolver mImageResolver; private CharSequence mConversationTitle; + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public MessagingLayout(@NonNull Context context) { super(context); @@ -212,8 +210,12 @@ public class MessagingLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -223,6 +225,12 @@ public class MessagingLayout extends FrameLayout // after groups are finalized, hide the first sender name if it's showing as the title mPeopleHelper.maybeHideFirstSenderName(mGroups, mIsOneToOne, mConversationTitle); updateImageMessages(); + + // Recycle everything at the end of the update, now that we know it's no longer needed. + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); + } + mToRecycle.clear(); } private void updateImageMessages() { @@ -263,18 +271,17 @@ public class MessagingLayout extends FrameLayout MessagingGroup group = oldGroups.get(i); if (!mGroups.contains(group)) { List<MessagingMessage> messages = group.getMessages(); - Runnable endRunnable = () -> { - mMessagingLinearLayout.removeTransientView(group); - group.recycle(); - }; boolean wasShown = group.isShown(); mMessagingLinearLayout.removeView(group); if (wasShown && !MessagingLinearLayout.isGone(group)) { mMessagingLinearLayout.addTransientView(group, 0); - group.removeGroupAnimated(endRunnable); + group.removeGroupAnimated(() -> { + mMessagingLinearLayout.removeTransientView(group); + group.recycle(); + }); } else { - endRunnable.run(); + mToRecycle.add(group); } mMessages.removeAll(messages); mHistoricMessages.removeAll(messages); diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java index cb1d387dbd07..c06f5f75514f 100644 --- a/core/java/com/android/internal/widget/MessagingLinearLayout.java +++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java @@ -365,6 +365,7 @@ public class MessagingLinearLayout extends ViewGroup { default int getExtraSpacing() { return 0; } + void recycle(); } public static class LayoutParams extends MarginLayoutParams { diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java index 8c8437951402..2cc0d2305a78 100644 --- a/core/java/com/android/internal/widget/MessagingMessage.java +++ b/core/java/com/android/internal/widget/MessagingMessage.java @@ -20,6 +20,7 @@ import android.app.ActivityManager; import android.app.Notification; import android.view.View; +import java.util.ArrayList; import java.util.Objects; /** @@ -96,8 +97,8 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { return sameAs(message.getMessage()); } - default void removeMessage() { - getGroup().removeMessage(this); + default void removeMessage(ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { + getGroup().removeMessage(this, toRecycle); } default void setMessagingGroup(MessagingGroup group) { diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index b1846d2402dd..cc7e9d95b4f8 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -435,15 +435,15 @@ public class SystemConfig { } /** Get privapp permission allowlist for an apk-in-apex. */ - public ArraySet<String> getApexPrivAppPermissions(String module, String packageName) { - return mApexPrivAppPermissions.getOrDefault(module, EMPTY_PERMISSIONS) - .get(packageName); + public ArraySet<String> getApexPrivAppPermissions(String apexName, String apkPackageName) { + return mApexPrivAppPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS) + .get(apkPackageName); } /** Get privapp permissions denylist for an apk-in-apex. */ - public ArraySet<String> getApexPrivAppDenyPermissions(String module, String packageName) { - return mApexPrivAppDenyPermissions.getOrDefault(module, EMPTY_PERMISSIONS) - .get(packageName); + public ArraySet<String> getApexPrivAppDenyPermissions(String apexName, String apkPackageName) { + return mApexPrivAppDenyPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS) + .get(apkPackageName); } public ArraySet<String> getVendorPrivAppPermissions(String packageName) { diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 4aa00f6117b9..3a76745cc4d9 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -361,7 +361,7 @@ cc_library_shared { "libwuffs_mirror_release_c", ], }, - linux_glibc: { + host_linux: { srcs: [ "android_content_res_ApkAssets.cpp", "android_database_CursorWindow.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index eedf7fa34a04..eba6cca76389 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -1567,6 +1567,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_classes), REG_JNI(register_android_graphics_BLASTBufferQueue), REG_JNI(register_android_graphics_GraphicBuffer), + REG_JNI(register_android_graphics_GraphicsStatsService), REG_JNI(register_android_graphics_SurfaceTexture), REG_JNI(register_android_database_CursorWindow), REG_JNI(register_android_database_SQLiteConnection), 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/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp index 0c05da551c8f..679a4f070290 100644 --- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp +++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp @@ -34,6 +34,7 @@ #include <sys/mman.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/system_properties.h> #include <vector> namespace android { @@ -43,10 +44,10 @@ using android::base::StringPrintf; using android::zygote::ZygoteFailure; // WARNING: Knows a little about the wire protocol used to communicate with Zygote. -// TODO: Fix error handling. +// Commands and nice names have large arbitrary size limits to avoid dynamic memory allocation. constexpr size_t MAX_COMMAND_BYTES = 32768; -constexpr size_t NICE_NAME_BYTES = 50; +constexpr size_t NICE_NAME_BYTES = 128; // A buffer optionally bundled with a file descriptor from which we can fill it. // Does not own the file descriptor; destroying a NativeCommandBuffer does not @@ -190,6 +191,9 @@ class NativeCommandBuffer { size_t copy_len = std::min(name_len, NICE_NAME_BYTES - 1); memcpy(mNiceName, arg_start + NN_LENGTH, copy_len); mNiceName[copy_len] = '\0'; + if (haveWrapProperty()) { + return false; + } continue; } if (arg_end - arg_start == IW_LENGTH @@ -222,6 +226,8 @@ class NativeCommandBuffer { } saw_setgid = true; } + // ro.debuggable can be handled entirely in the child unless --invoke-with is also specified. + // Thus we do not need to check it here. } return saw_runtime_args && saw_setuid && saw_setgid; } @@ -249,6 +255,14 @@ class NativeCommandBuffer { } private: + bool haveWrapProperty() { + static const char* WRAP = "wrap."; + static const size_t WRAP_LENGTH = strlen(WRAP); + char propNameBuf[WRAP_LENGTH + NICE_NAME_BYTES]; + strcpy(propNameBuf, WRAP); + strlcpy(propNameBuf + WRAP_LENGTH, mNiceName, NICE_NAME_BYTES); + return __system_property_find(propNameBuf) != nullptr; + } // Picky version of atoi(). No sign or unexpected characters allowed. Return -1 on failure. static int digitsVal(char* start, char* end) { int result = 0; @@ -269,7 +283,7 @@ class NativeCommandBuffer { uint32_t mNext; // Index of first character past last line returned by readLine. int32_t mLinesLeft; // Lines in current command that haven't yet been read. int mFd; // Open file descriptor from which we can read more. -1 if none. - char mNiceName[NICE_NAME_BYTES]; + char mNiceName[NICE_NAME_BYTES]; // Always null terminated. char mBuffer[MAX_COMMAND_BYTES]; }; @@ -372,6 +386,7 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly( jint minUid, jstring managed_nice_name) { + ALOGI("Entering forkRepeatedly native zygote loop"); NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer); int session_socket = n_buffer->getFd(); std::vector<int> session_socket_fds {session_socket}; @@ -400,7 +415,8 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly( socklen_t cred_size = sizeof credentials; if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1 || cred_size != sizeof credentials) { - fail_fn_1(CREATE_ERROR("ForkMany failed to get initial credentials, %s", strerror(errno))); + fail_fn_1(CREATE_ERROR("ForkRepeatedly failed to get initial credentials, %s", + strerror(errno))); } bool first_time = true; diff --git a/core/proto/android/os/batteryusagestats.proto b/core/proto/android/os/batteryusagestats.proto index cc90e05de744..856bc839aee5 100644 --- a/core/proto/android/os/batteryusagestats.proto +++ b/core/proto/android/os/batteryusagestats.proto @@ -76,6 +76,7 @@ message BatteryUsageStatsAtomsProto { FOREGROUND = 1; BACKGROUND = 2; FOREGROUND_SERVICE = 3; + CACHED = 4; } optional ProcessState process_state = 2; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index becac7f96428..729bc8294dc4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1030,10 +1030,10 @@ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission must not be used and the READ_EXTERNAL_STORAGE permission must be used instead. <p>Protection level: dangerous --> - <permission android:name="android.permission.READ_MEDIA_IMAGE" + <permission android:name="android.permission.READ_MEDIA_IMAGES" android:permissionGroup="android.permission-group.UNDEFINED" - android:label="@string/permlab_readMediaImage" - android:description="@string/permdesc_readMediaImage" + android:label="@string/permlab_readMediaImages" + android:description="@string/permdesc_readMediaImages" android:protectionLevel="dangerous" /> <!-- Allows an application to write to external storage. @@ -6051,10 +6051,10 @@ <permission android:name="android.permission.MANAGE_APPOPS" android:protectionLevel="signature" /> - <!-- @hide Permission that allows background clipboard access. - <p>Not for use by third-party applications. --> + <!-- @SystemApi Permission that allows background clipboard access. + @hide Not for use by third-party applications. --> <permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND" - android:protectionLevel="signature" /> + android:protectionLevel="internal|role" /> <!-- @hide Permission that suppresses the notification when the clipboard is accessed. <p>Not for use by third-party applications. --> <permission android:name="android.permission.SUPPRESS_CLIPBOARD_ACCESS_NOTIFICATION" @@ -6160,10 +6160,10 @@ <!-- Allows input events to be monitored. Very dangerous! @hide --> <permission android:name="android.permission.MONITOR_INPUT" android:protectionLevel="signature|recents" /> - <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current - window to the window where the touch currently is on top of. @hide --> + <!-- @SystemApi Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the + current window to the window where the touch currently is on top of. @hide --> <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES" - android:protectionLevel="signature|recents" /> + android:protectionLevel="signature|privileged|recents|role" /> <!-- Allows the caller to change the associations between input devices and displays. Very dangerous! @hide --> <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY" @@ -6420,6 +6420,12 @@ <permission android:name="android.permission.WRITE_SECURITY_LOG" android:protectionLevel="signature|privileged" /> + <!-- Allows an UID to be visible to the application based on an interaction between the + two apps. This permission is not intended to be held by apps. + @hide @TestApi --> + <permission android:name="android.permission.MAKE_UID_VISIBLE" + android:protectionLevel="signature" /> + <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml index f8c04517800a..cb4462c9a169 100644 --- a/core/res/res/drawable-nodpi/stat_sys_adb.xml +++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml @@ -1,5 +1,5 @@ <!-- -Copyright (C) 2021 The Android Open Source Project +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. @@ -13,11 +13,78 @@ Copyright (C) 2021 The Android Open Source Project See the License for the specific language governing permissions and limitations under the License. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path android:pathData="M18 9c0-.69268-.1174-1.35795-.3333-1.97699C16.8495 4.68061 14.621 3 12 3 8.68629 3 6 5.68629 6 9v3h6M6 15c0 .6927.11738 1.3579.33333 1.977C7.15047 19.3194 9.37897 21 12 21c3.3137 0 6-2.6863 6-6v-3h-6" android:strokeColor="#000000" android:strokeWidth="2" android:fillColor="#00000000"/> - <path android:fillColor="#000000" android:pathData="M10 7a1 1 0 1 0 0 2 1 1 0 1 0 0-2zM14 7a1 1 0 1 0 0 2 1 1 0 1 0 0-2z"/> - <path android:pathData="M6 3l1.5 1.5M18 3l-1.5 1.5" android:strokeColor="#000000" android:strokeWidth="2" android:fillColor="#000000"/> +<vector android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24" + xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:pathData=" + M22.45 11.94 + l-.58-.21 + a1.19 1.19 0 0 1-.26-2.12 + l.51-.34 + a1.2 1.2 0 0 0-.83-2.19 + l-.61.08 + a1.2 1.2 0 0 1-1.21-1.76 + l.29-.54 + A1.2 1.2 0 0 0 18 3.31 + l-.5.36 + a1.21 1.21 0 0 1-1.9-1 + v-.61 + a1.2 1.2 0 0 0-2.27-.56 + l-.26.5 + a1.2 1.2 0 0 1-2.14 0 + l-.28-.54 + a1.2 1.2 0 0 0-2.27.56 + v.61 + a1.21 1.21 0 0 1-1.9 1 + L6 3.31 + a1.2 1.2 0 0 0-1.76 1.55 + l.29.54 + a1.2 1.2 0 0 1-1.21 1.76 + l-.61-.08 + a1.2 1.2 0 0 0-.83 2.19 + l.51.34 + a1.19 1.19 0 0 1-.26 2.12 + l-.58.21 + a1.21 1.21 0 0 0 .29 2.33 + l.61.06 + a1.2 1.2 0 0 1 .76 2 + l-.42.46 + a1.2 1.2 0 0 0 1.33 1.92 + l.57-.22 + a1.21 1.21 0 0 1 1.61 1.42 + l-.16.59 + a1.2 1.2 0 0 0 2.07 1.09 + l.4-.47 + a1.2 1.2 0 0 1 2.08.51 + l.14.6 + a1.2 1.2 0 0 0 2.34 0 + l.14-.6 + a1.2 1.2 0 0 1 2.08-.51 + l.4.47 + a1.2 1.2 0 0 0 2.07-1.09 + l-.16-.59 + a1.21 1.21 0 0 1 1.61-1.42 + l.57.22 + a1.2 1.2 0 0 0 1.33-1.92 + l-.42-.46 + a1.2 1.2 0 0 1 .76-2 + l.61-.06 + a1.21 1.21 0 0 0 .29-2.33 + z + M12 19 + a7 7 0 1 1 7-7 7 7 0 0 1-7 7 + z + " + android:fillColor="#000000" /> + <path android:pathData=" + M9 7.75 + a.75.75 0 1 0 0 1.5.75.75 0 1 0 0-1.5 + z + M15 7.75 + a.75.75 0 1 0 0 1.5.75.75 0 1 0 0-1.5 + z + " + android:fillColor="#000000" /> + <path android:strokeColor="#000000" android:strokeMiterLimit="10" android:strokeWidth="2" + android:pathData="M4 12h16M12 12v8" /> </vector> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index da5f8998d156..2107f651eade 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5479,9 +5479,9 @@ <enum name="none" value="0" /> <!-- Use the least restrictive rule for line-breaking. --> <enum name="loose" value="1" /> - <!-- Indicate breaking text with the most comment set of line-breaking rules. --> + <!-- Indicates breaking text with the most comment set of line-breaking rules. --> <enum name="normal" value="2" /> - <!-- ndicates breaking text with the most strictest line-breaking rules. --> + <!-- Indicates breaking text with the most strictest line-breaking rules. --> <enum name="strict" value="3" /> </attr> <!-- Specify the phrase-based line break can be used when calculating the text wrapping.--> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 0a572be35023..62b3054589e0 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2723,7 +2723,7 @@ <string name="config_bandwidthEstimateSource">bandwidth_estimator</string> <!-- Whether force to enable telephony new data stack or not --> - <bool name="config_force_enable_telephony_new_data_stack">true</bool> + <bool name="config_force_enable_telephony_new_data_stack">false</bool> <!-- Whether WiFi display is supported by this device. There are many prerequisites for this feature to work correctly. @@ -2988,6 +2988,12 @@ </string-array> + <!-- When migrating notification settings into the permission framework, whether all existing + apps should be marked as 'user-set' (true) or whether only the apps that have explicitly + modified notification settings should be marked as 'user-set' (false). Users will not see + system generated permission prompts for 'user-set' apps. --> + <bool name="config_notificationForceUserSetOnUpgrade">true</bool> + <!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM --> <integer name="config_toastDefaultGravity">0x00000051</integer> @@ -4851,6 +4857,7 @@ <item>0.25</item> <item>0.5</item> <item>0.75</item> + <item>0.875</item> </string-array> <!-- Messages that should not be shown to the user during face auth enrollment. This should be diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index f803c35f7f1d..4c71b3abd00c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1918,9 +1918,9 @@ <string name="permdesc_readMediaVideo">Allows the app to read video files from your shared storage.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can read from. [CHAR LIMIT=none] --> - <string name="permlab_readMediaImage">read image files from shared storage</string> + <string name="permlab_readMediaImages">read image files from shared storage</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can read from. [CHAR LIMIT=none] --> - <string name="permdesc_readMediaImage">Allows the app to read image files from your shared storage.</string> + <string name="permdesc_readMediaImages">Allows the app to read image files from your shared storage.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can write to. [CHAR LIMIT=none] --> <string name="permlab_sdcardWrite">modify or delete the contents of your shared storage</string> @@ -2414,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. --> @@ -5739,7 +5739,7 @@ <!-- Content for the log access confirmation dialog. [CHAR LIMIT=NONE]--> <string name="log_access_confirmation_body">Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs. - \n\nIf you don’t allow this app to access all device logs, it can still access its own logs, and your device manufacturer may still be able to access some logs or info on your device. Learn more + \n\nIf you don’t allow this app to access all device logs, it can still access its own logs and your device manufacturer may still be able to access some logs or info on your device. Learn more </string> <!-- Privacy notice do not show [CHAR LIMIT=20] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6f34b3f899f1..1f0b22b9e460 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4770,5 +4770,6 @@ <java-symbol type="integer" name="config_bg_current_drain_exempted_types" /> <java-symbol type="bool" name="config_bg_current_drain_high_threshold_by_bg_location" /> <java-symbol type="drawable" name="ic_swap_horiz" /> + <java-symbol type="bool" name="config_notificationForceUserSetOnUpgrade" /> </resources> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java index 6a53f6843d48..19bb718578a0 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java @@ -188,6 +188,9 @@ public class BatteryConsumerData { case BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE: label = "FGS"; break; + case BatteryConsumer.PROCESS_STATE_CACHED: + label = "cached"; + break; default: continue; } diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java index 23b12cf3ea4b..fd08e3c789f7 100644 --- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java +++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java @@ -242,13 +242,17 @@ public class BatteryUsageStatsPulledTest { BatteryConsumer.PROCESS_STATE_BACKGROUND); final BatteryConsumer.Key keyFgs = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); + final BatteryConsumer.Key keyCached = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU, + BatteryConsumer.PROCESS_STATE_CACHED); uidBuilder.setConsumedPower(keyFg, 9100, BatteryConsumer.POWER_MODEL_POWER_PROFILE) .setUsageDurationMillis(keyFg, 8100) .setConsumedPower(keyBg, 9200, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) .setUsageDurationMillis(keyBg, 8200) .setConsumedPower(keyFgs, 9300, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) - .setUsageDurationMillis(keyFgs, 8300); + .setUsageDurationMillis(keyFgs, 8300) + .setConsumedPower(keyCached, 9400, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) + .setUsageDurationMillis(keyFgs, 8400); builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid1) .setPackageWithHighestDrain("myPackage1") diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 5c9044c56f95..beadc4464516 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -424,6 +424,7 @@ public class TransactionParcelTests { @Override public void bindApplication(String s, ApplicationInfo applicationInfo, + String sdkSandboxClientAppPackage, ProviderInfoList list, ComponentName componentName, ProfilerInfo profilerInfo, Bundle bundle, IInstrumentationWatcher iInstrumentationWatcher, IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1, diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java index 2bdcc284154b..75390a282af9 100644 --- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java +++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java @@ -180,6 +180,61 @@ public class IconTest extends AndroidTestCase { } } + /** + * Icon resource test that ensures we can load and draw non-bitmaps. (In this case, + * stat_sys_adb is assumed, and asserted, to be a vector drawable.) + */ + @SmallTest + public void testWithStatSysAdbResource() throws Exception { + // establish reference bitmap + final float dp = getContext().getResources().getDisplayMetrics().density; + final int stat_sys_adb_width = (int) (24 * dp); + final int stat_sys_adb_height = (int) (24 * dp); + + final Drawable stat_sys_adb = getContext() + .getDrawable(com.android.internal.R.drawable.stat_sys_adb); + if (!(stat_sys_adb instanceof VectorDrawable)) { + fail("stat_sys_adb is a " + stat_sys_adb.toString() + + ", not a VectorDrawable; stat_sys_adb malformed"); + } + + if (stat_sys_adb.getIntrinsicWidth() != stat_sys_adb_width) { + fail("intrinsic width of stat_sys_adb is not 24dp; stat_sys_adb malformed"); + } + if (stat_sys_adb.getIntrinsicHeight() != stat_sys_adb_height) { + fail("intrinsic height of stat_sys_adb is not 24dp; stat_sys_adb malformed"); + } + final Bitmap referenceBitmap = Bitmap.createBitmap( + stat_sys_adb_width, + stat_sys_adb_height, + Bitmap.Config.ARGB_8888); + stat_sys_adb.setBounds(0, 0, stat_sys_adb_width, stat_sys_adb_height); + stat_sys_adb.draw(new Canvas(referenceBitmap)); + + final Icon im1 = Icon.createWithResource(getContext(), + com.android.internal.R.drawable.stat_sys_adb); + final Drawable draw1 = im1.loadDrawable(getContext()); + + assertEquals(stat_sys_adb.getIntrinsicWidth(), draw1.getIntrinsicWidth()); + assertEquals(stat_sys_adb.getIntrinsicHeight(), draw1.getIntrinsicHeight()); + assertEquals(im1.getResId(), com.android.internal.R.drawable.stat_sys_adb); + + final Bitmap test1 = Bitmap.createBitmap( + draw1.getIntrinsicWidth(), + draw1.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight()); + draw1.draw(new Canvas(test1)); + + final File dir = getContext().getExternalFilesDir(null); + test1.compress(Bitmap.CompressFormat.PNG, 100, + new FileOutputStream(new File(dir, "testWithVectorDrawableResource-test.png"))); + if (!equalBitmaps(referenceBitmap, test1)) { + findBitmapDifferences(referenceBitmap, test1); + fail("testWithFile: file1 differs, check " + dir); + } + } + @SmallTest public void testWithFile() throws Exception { final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) 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/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index f5cbffb64bb5..7ccb9d963ee6 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -17,6 +17,8 @@ package com.android.internal.os; import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; +import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; +import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT; import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR; import static android.os.BatteryStats.STATS_SINCE_CHARGED; import static android.os.BatteryStats.WAKE_TYPE_PARTIAL; @@ -24,7 +26,10 @@ import static android.os.BatteryStats.WAKE_TYPE_PARTIAL; import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU; import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY; +import static org.mockito.Mockito.mock; + import android.app.ActivityManager; +import android.app.usage.NetworkStatsManager; import android.os.BatteryStats; import android.os.BatteryStats.HistoryItem; import android.os.BatteryStats.Uid.Sensor; @@ -34,6 +39,7 @@ import android.os.WorkSource; import android.telephony.Annotation; import android.telephony.CellSignalStrength; import android.telephony.DataConnectionRealTimeInfo; +import android.telephony.ModemActivityInfo; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.SparseIntArray; @@ -48,6 +54,8 @@ import com.android.internal.power.MeasuredEnergyStats; import junit.framework.TestCase; +import org.mockito.Mock; + import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -72,6 +80,13 @@ public class BatteryStatsNoteTest extends TestCase { private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID); private static final WorkSource WS = new WorkSource(UID); + enum ModemState { + SLEEP, IDLE, RECEIVING, TRANSMITTING + } + + @Mock + NetworkStatsManager mNetworkStatsManager; + /** * Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked. */ @@ -1173,69 +1188,29 @@ public class BatteryStatsNoteTest extends TestCase { } @SmallTest - public void testGetPerStateActiveRadioDurationMs() { + public void testGetPerStateActiveRadioDurationMs_noModemActivity() { final MockClock clock = new MockClock(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock); - final int ratCount = BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT; + final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT; final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1; final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels(); final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount]; + final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount]; + final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount]; for (int rat = 0; rat < ratCount; rat++) { for (int freq = 0; freq < frequencyCount; freq++) { + // Should have no RX data without Modem Activity Info + expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE; for (int txLvl = 0; txLvl < txLevelCount; txLvl++) { expectedDurationsMs[rat][freq][txLvl] = 0; + // Should have no TX data without Modem Activity Info + expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE; } } } - class ModemAndBatteryState { - public long currentTimeMs = 100; - public boolean onBattery = false; - public boolean modemActive = false; - @Annotation.NetworkType - public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - @BatteryStats.RadioAccessTechnology - public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER; - @ServiceState.FrequencyRange - public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN; - public SparseIntArray currentSignalStrengths = new SparseIntArray(); - - void setOnBattery(boolean onBattery) { - this.onBattery = onBattery; - bi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000, - currentTimeMs * 1000); - } - - void setModemActive(boolean active) { - modemActive = active; - final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH - : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; - bi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID); - } - - void setRatType(@Annotation.NetworkType int dataType, - @BatteryStats.RadioAccessTechnology int rat) { - currentNetworkDataType = dataType; - currentRat = rat; - bi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE, - currentFrequencyRange); - } - - void setFrequencyRange(@ServiceState.FrequencyRange int frequency) { - currentFrequencyRange = frequency; - bi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true, - ServiceState.STATE_IN_SERVICE, frequency); - } - - void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) { - currentSignalStrengths.put(rat, strength); - final int size = currentSignalStrengths.size(); - final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1); - bi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths); - } - } - final ModemAndBatteryState state = new ModemAndBatteryState(); + final ModemAndBatteryState state = new ModemAndBatteryState(bi, null); IntConsumer incrementTime = inc -> { state.currentTimeMs += inc; @@ -1253,6 +1228,7 @@ public class BatteryStatsNoteTest extends TestCase { expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc; }; + state.setOnBattery(false); state.setModemActive(false); state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN, @@ -1260,95 +1236,367 @@ public class BatteryStatsNoteTest extends TestCase { state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN); state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER, CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // While not on battery, the timers should not increase. state.setModemActive(true); incrementTime.accept(100); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR); incrementTime.accept(200); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR, CellSignalStrength.SIGNAL_STRENGTH_GOOD); incrementTime.accept(500); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE); incrementTime.accept(300); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setRatType(TelephonyManager.NETWORK_TYPE_LTE, BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE); incrementTime.accept(400); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, CellSignalStrength.SIGNAL_STRENGTH_MODERATE); incrementTime.accept(500); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should // start counting up. state.setOnBattery(true); incrementTime.accept(600); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); - + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Changing LTE signal strength should be tracked. state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, CellSignalStrength.SIGNAL_STRENGTH_POOR); incrementTime.accept(700); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN); incrementTime.accept(800); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, CellSignalStrength.SIGNAL_STRENGTH_GOOD); incrementTime.accept(900); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, CellSignalStrength.SIGNAL_STRENGTH_GREAT); incrementTime.accept(1000); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Change in the signal strength of nonactive RAT should not affect anything. state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER, CellSignalStrength.SIGNAL_STRENGTH_POOR); incrementTime.accept(1100); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Changing to OTHER Rat should start tracking the poor signal strength. state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA, BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER); incrementTime.accept(1200); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Noting frequency change should not affect non NR Rat. state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH); incrementTime.accept(1300); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Now the NR Rat, HIGH frequency range, good signal strength should start counting. state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR); incrementTime.accept(1400); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Noting frequency change should not affect non NR Rat. state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW); incrementTime.accept(1500); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); // Modem no longer active, should not be tracking any more. state.setModemActive(false); incrementTime.accept(1500); - checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + } + + @SmallTest + public void testGetPerStateActiveRadioDurationMs_withModemActivity() { + final MockClock clock = new MockClock(); // holds realtime and uptime in ms + final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock); + bi.setPowerProfile(mock(PowerProfile.class)); + final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT; + final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1; + final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels(); + + final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount]; + final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount]; + final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount]; + for (int rat = 0; rat < ratCount; rat++) { + for (int freq = 0; freq < frequencyCount; freq++) { + if (rat != RADIO_ACCESS_TECHNOLOGY_NR + && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) { + // Only the NR RAT should have per frequency data. + expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE; + } else { + expectedRxDurationsMs[rat][freq] = 0; + } + expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE; + + for (int txLvl = 0; txLvl < txLevelCount; txLvl++) { + expectedDurationsMs[rat][freq][txLvl] = 0; + + if (rat != RADIO_ACCESS_TECHNOLOGY_NR + && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) { + // Only the NR RAT should have per frequency data. + expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE; + } else { + expectedTxDurationsMs[rat][freq][txLvl] = 0; + } + expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE; + } + } + } + + final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L); + final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai); + + IntConsumer incrementTime = inc -> { + state.currentTimeMs += inc; + clock.realtime = clock.uptime = state.currentTimeMs; + + // If the device is not on battery, no timers should increment. + if (!state.onBattery) return; + // If the modem is not active, no timers should increment. + if (!state.modemActive) return; + + final int currRat = state.currentRat; + final int currFreqRange = + currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0; + int currSignalStrength = state.currentSignalStrengths.get(currRat); + + expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc; + + // Evaluate the HAL provided time in states. + switch (state.modemState) { + case SLEEP: + long sleepMs = state.modemActivityInfo.getSleepTimeMillis(); + state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc); + break; + case IDLE: + long idleMs = state.modemActivityInfo.getIdleTimeMillis(); + state.modemActivityInfo.setIdleTimeMillis(idleMs + inc); + break; + case RECEIVING: + long rxMs = state.modemActivityInfo.getReceiveTimeMillis(); + state.modemActivityInfo.setReceiveTimeMillis(rxMs + inc); + expectedRxDurationsMs[currRat][currFreqRange] += inc; + break; + case TRANSMITTING: + int[] txMs = state.modemActivityInfo.getTransmitTimeMillis(); + txMs[currSignalStrength] += inc; + state.modemActivityInfo.setTransmitTimeMillis(txMs); + expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc; + break; + } + }; + + state.setOnBattery(false); + state.setModemActive(false); + state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN, + BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER); + state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN); + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER, + CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // While not on battery, the timers should not increase. + state.setModemActive(true); + incrementTime.accept(100); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR); + incrementTime.accept(200); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR, + CellSignalStrength.SIGNAL_STRENGTH_GOOD); + incrementTime.accept(500); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE); + incrementTime.accept(300); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setRatType(TelephonyManager.NETWORK_TYPE_LTE, + BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE); + incrementTime.accept(400); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, + CellSignalStrength.SIGNAL_STRENGTH_MODERATE); + incrementTime.accept(500); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // Data will now be available. + for (int rat = 0; rat < ratCount; rat++) { + for (int freq = 0; freq < frequencyCount; freq++) { + if (rat == RADIO_ACCESS_TECHNOLOGY_NR + || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) { + // Only the NR RAT should have per frequency data. + expectedRxDurationsMs[rat][freq] = 0; + } + for (int txLvl = 0; txLvl < txLevelCount; txLvl++) { + if (rat == RADIO_ACCESS_TECHNOLOGY_NR + || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) { + // Only the NR RAT should have per frequency data. + expectedTxDurationsMs[rat][freq][txLvl] = 0; + } + } + } + } + + // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should + // start counting up. + state.setOnBattery(true); + incrementTime.accept(300); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(500); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(600); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + // Changing LTE signal strength should be tracked. + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, + CellSignalStrength.SIGNAL_STRENGTH_POOR); + incrementTime.accept(300); + state.setModemState(ModemState.SLEEP); + incrementTime.accept(1000); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(700); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, + CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN); + incrementTime.accept(800); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(222); + state.setModemState(ModemState.IDLE); + incrementTime.accept(111); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(7777); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, + CellSignalStrength.SIGNAL_STRENGTH_GOOD); + incrementTime.accept(88); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(900); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE, + CellSignalStrength.SIGNAL_STRENGTH_GREAT); + incrementTime.accept(123); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(333); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(1000); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(555); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // Change in the signal strength of nonactive RAT should not affect anything. + state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER, + CellSignalStrength.SIGNAL_STRENGTH_POOR); + incrementTime.accept(631); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(321); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(99); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // Changing to OTHER Rat should start tracking the poor signal strength. + state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA, + BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER); + incrementTime.accept(1200); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // Noting frequency change should not affect non NR Rat. + state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH); + incrementTime.accept(444); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(1300); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // Now the NR Rat, HIGH frequency range, good signal strength should start counting. + state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR); + incrementTime.accept(1400); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + + // Frequency changed to low. + state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW); + incrementTime.accept(852); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(157); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(1500); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + // Modem no longer active, should not be tracking any more. + state.setModemActive(false); + incrementTime.accept(1500); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); } private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) { @@ -1426,28 +1674,124 @@ public class BatteryStatsNoteTest extends TestCase { } private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs, + long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs, BatteryStatsImpl bi, long currentTimeMs) { for (int rat = 0; rat < expectedDurationsMs.length; rat++) { final long[][] expectedRatDurationsMs = expectedDurationsMs[rat]; for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) { + final long expectedRxDurationMs = expectedRxDurationsMs[rat][freq]; + + // Build a verbose fail message, just in case. + final StringBuilder rxFailSb = new StringBuilder(); + rxFailSb.append("Wrong time in Rx state for RAT:"); + rxFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]); + rxFailSb.append(", frequency:"); + rxFailSb.append(ServiceState.frequencyRangeToString(freq)); + assertEquals(rxFailSb.toString(), expectedRxDurationMs, + bi.getActiveRxRadioDurationMs(rat, freq, currentTimeMs)); + final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq]; for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) { final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength]; + final long expectedTxDurationMs = expectedTxDurationsMs[rat][freq][strength]; final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq, strength, currentTimeMs); - // Build a verbose fail message, just in case. - final StringBuilder sb = new StringBuilder(); - sb.append("Wrong time in state for RAT:"); - sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]); - sb.append(", frequency:"); - sb.append(ServiceState.frequencyRangeToString(freq)); - sb.append(", strength:"); - sb.append(strength); - - assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs); + final StringBuilder failSb = new StringBuilder(); + failSb.append("Wrong time in state for RAT:"); + failSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]); + failSb.append(", frequency:"); + failSb.append(ServiceState.frequencyRangeToString(freq)); + failSb.append(", strength:"); + failSb.append(strength); + assertEquals(failSb.toString(), expectedSignalStrengthDurationMs, + actualDurationMs); + + final StringBuilder txFailSb = new StringBuilder(); + txFailSb.append("Wrong time in Tx state for RAT:"); + txFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]); + txFailSb.append(", frequency:"); + txFailSb.append(ServiceState.frequencyRangeToString(freq)); + txFailSb.append(", strength:"); + txFailSb.append(strength); + assertEquals(txFailSb.toString(), expectedTxDurationMs, + bi.getActiveTxRadioDurationMs(rat, freq, strength, currentTimeMs)); } } } } + + private class ModemAndBatteryState { + public long currentTimeMs = 100; + public boolean onBattery = false; + public boolean modemActive = false; + @Annotation.NetworkType + public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + @BatteryStats.RadioAccessTechnology + public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER; + @ServiceState.FrequencyRange + public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN; + public SparseIntArray currentSignalStrengths = new SparseIntArray(); + public ModemState modemState = ModemState.SLEEP; + public ModemActivityInfo modemActivityInfo; + + private final MockBatteryStatsImpl mBsi; + + ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai) { + mBsi = bsi; + modemActivityInfo = mai; + } + + void setOnBattery(boolean onBattery) { + this.onBattery = onBattery; + mBsi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000, + currentTimeMs * 1000); + mBsi.setOnBatteryInternal(onBattery); + noteModemControllerActivity(); + } + + void setModemActive(boolean active) { + modemActive = active; + final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH + : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; + mBsi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID); + noteModemControllerActivity(); + } + + void setRatType(@Annotation.NetworkType int dataType, + @BatteryStats.RadioAccessTechnology int rat) { + currentNetworkDataType = dataType; + currentRat = rat; + mBsi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE, + currentFrequencyRange); + } + + void setFrequencyRange(@ServiceState.FrequencyRange int frequency) { + currentFrequencyRange = frequency; + mBsi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true, + ServiceState.STATE_IN_SERVICE, frequency); + } + + void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) { + currentSignalStrengths.put(rat, strength); + final int size = currentSignalStrengths.size(); + final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1); + mBsi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths); + } + + void setModemState(ModemState state) { + modemState = state; + } + + void noteModemControllerActivity() { + if (modemActivityInfo == null) return; + modemActivityInfo.setTimestamp(currentTimeMs); + ModemActivityInfo copy = new ModemActivityInfo(modemActivityInfo.getTimestampMillis(), + modemActivityInfo.getSleepTimeMillis(), modemActivityInfo.getIdleTimeMillis(), + modemActivityInfo.getTransmitTimeMillis().clone(), + modemActivityInfo.getReceiveTimeMillis()); + mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE, + currentTimeMs, currentTimeMs, mNetworkStatsManager); + } + } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java index 0e394c1ec7fd..bfb34499984b 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java @@ -30,6 +30,7 @@ import junit.framework.TestCase; public class BatteryStatsSensorTest extends TestCase { private static final int UID = 10500; + private static final int UID_2 = 10501; // second uid for testing pool usage private static final int SENSOR_ID = -10000; @SmallTest @@ -239,7 +240,6 @@ public class BatteryStatsSensorTest extends TestCase { @SmallTest public void testPooledBackgroundUsage() throws Exception { - final int UID_2 = 20000; // second uid for testing pool usage final MockClock clocks = new MockClock(); MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); bi.mForceOnBattery = true; diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java index 5adc9bdf0d00..483224cf353d 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java @@ -20,6 +20,7 @@ import static android.os.BatteryConsumer.POWER_COMPONENT_ANY; import static android.os.BatteryConsumer.POWER_MODEL_MEASURED_ENERGY; import static android.os.BatteryConsumer.POWER_MODEL_UNDEFINED; import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND; +import static android.os.BatteryConsumer.PROCESS_STATE_CACHED; import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND; import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE; @@ -83,7 +84,7 @@ public class BatteryUsageStatsTest { final Parcel parcel = Parcel.obtain(); parcel.writeParcelable(outBatteryUsageStats, 0); - assertThat(parcel.dataSize()).isLessThan(7000); + assertThat(parcel.dataSize()).isLessThan(8000); parcel.setDataPosition(0); @@ -155,10 +156,11 @@ public class BatteryUsageStatsTest { assertThat(dump).contains("cpu(fg): 2333 apps: 1333 duration: 3s 332ms"); assertThat(dump).contains("cpu(bg): 2444 apps: 1444 duration: 4s 442ms"); assertThat(dump).contains("cpu(fgs): 2555 apps: 1555 duration: 5s 552ms"); + assertThat(dump).contains("cpu(cached): 123 apps: 123 duration: 456ms"); assertThat(dump).contains("FOO: 20200 apps: 10200 duration: 20s 400ms"); - assertThat(dump).contains("UID 271: 1200 fg: 1777 bg: 1888 fgs: 1999 ( screen=300 " - + "cpu=400 (600ms) cpu:fg=1777 (7s 771ms) cpu:bg=1888 (8s 881ms) " - + "cpu:fgs=1999 (9s 991ms) FOO=500 )"); + assertThat(dump).contains("UID 271: 1200 fg: 1777 bg: 1888 fgs: 1999 cached: 123 " + + "( screen=300 cpu=400 (600ms) cpu:fg=1777 (7s 771ms) cpu:bg=1888 (8s 881ms) " + + "cpu:fgs=1999 (9s 991ms) cpu:cached=123 (456ms) FOO=500 )"); assertThat(dump).contains("User 42: 30.0 ( cpu=10.0 (30ms) FOO=20.0 )"); } @@ -193,13 +195,15 @@ public class BatteryUsageStatsTest { 5321, 7432, 423, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 745, POWER_MODEL_UNDEFINED, 956, 1167, 1478, - true, 3554, 3776, 3998, 3554, 15542, 3776, 17762, 3998, 19982); + true, 3554, 3776, 3998, 444, 3554, 15542, 3776, 17762, 3998, 19982, + 444, 1110); } else if (uidBatteryConsumer.getUid() == APP_UID2) { assertUidBatteryConsumer(uidBatteryConsumer, 1332, "bar", 1111, 2222, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 555, 666, 777, - true, 1777, 1888, 1999, 1777, 7771, 1888, 8881, 1999, 9991); + true, 1777, 1888, 1999, 321, 1777, 7771, 1888, 8881, 1999, 9991, + 321, 654); } else { fail("Unexpected UID " + uidBatteryConsumer.getUid()); } @@ -267,17 +271,17 @@ public class BatteryUsageStatsTest { 1000, 2000, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 500, 600, 800, - 1777, 7771, 1888, 8881, 1999, 9991); + 1777, 7771, 1888, 8881, 1999, 9991, 123, 456); addAggregateBatteryConsumer(builder, BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0, 10100, 10200, 10300, 10400, - 1333, 3331, 1444, 4441, 1555, 5551); + 1333, 3331, 1444, 4441, 1555, 5551, 123, 456); addAggregateBatteryConsumer(builder, BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 30000, 20100, 20200, 20300, 20400, - 2333, 3332, 2444, 4442, 2555, 5552); + 2333, 3332, 2444, 4442, 2555, 5552, 123, 456); if (includeUserBatteryConsumer) { builder.getOrCreateUserBatteryConsumerBuilder(USER_ID) @@ -310,23 +314,23 @@ public class BatteryUsageStatsTest { 4321, 5432, 123, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 345, POWER_MODEL_MEASURED_ENERGY, 456, 567, 678, - 1777, 7771, 1888, 8881, 1999, 9991); + 1777, 7771, 1888, 8881, 1999, 9991, 321, 654); addUidBatteryConsumer(builder, batteryStats, APP_UID2, "bar", 1111, 2222, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 555, 666, 777, - 1777, 7771, 1888, 8881, 1999, 9991); + 1777, 7771, 1888, 8881, 1999, 9991, 321, 654); addAggregateBatteryConsumer(builder, BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0, 10123, 10234, 10345, 10456, - 4333, 3334, 5444, 4445, 6555, 5556); + 4333, 3334, 5444, 4445, 6555, 5556, 321, 654); addAggregateBatteryConsumer(builder, BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 12345, 20111, 20222, 20333, 20444, - 7333, 3337, 8444, 4448, 9555, 5559); + 7333, 3337, 8444, 4448, 9555, 5559, 123, 456); return builder; } @@ -337,7 +341,7 @@ public class BatteryUsageStatsTest { int screenPowerModel, double cpuPower, int cpuPowerModel, double customComponentPower, int cpuDuration, int customComponentDuration, double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground, - double cpuPowerFgs, int cpuDurationFgs) { + double cpuPowerFgs, int cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) { final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(uid); final UidBatteryConsumer.Builder uidBuilder = builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid); @@ -365,6 +369,9 @@ public class BatteryUsageStatsTest { final BatteryConsumer.Key cpuFgsKey = uidBuilder.getKey( BatteryConsumer.POWER_COMPONENT_CPU, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); + final BatteryConsumer.Key cachedKey = uidBuilder.getKey( + BatteryConsumer.POWER_COMPONENT_CPU, + BatteryConsumer.PROCESS_STATE_CACHED); uidBuilder .setConsumedPower(cpuFgKey, cpuPowerForeground, BatteryConsumer.POWER_MODEL_POWER_PROFILE) @@ -374,7 +381,10 @@ public class BatteryUsageStatsTest { .setUsageDurationMillis(cpuBgKey, cpuDurationBackground) .setConsumedPower(cpuFgsKey, cpuPowerFgs, BatteryConsumer.POWER_MODEL_POWER_PROFILE) - .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs); + .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs) + .setConsumedPower(cachedKey, cpuPowerCached, + BatteryConsumer.POWER_MODEL_POWER_PROFILE) + .setUsageDurationMillis(cachedKey, cpuDurationCached); } } @@ -382,7 +392,7 @@ public class BatteryUsageStatsTest { double consumedPower, int cpuPower, int customComponentPower, int cpuDuration, int customComponentDuration, double cpuPowerForeground, long cpuDurationForeground, double cpuPowerBackground, long cpuDurationBackground, double cpuPowerFgs, - long cpuDurationFgs) { + long cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) { final AggregateBatteryConsumer.Builder aggBuilder = builder.getAggregateBatteryConsumerBuilder(scope) .setConsumedPower(consumedPower) @@ -406,6 +416,9 @@ public class BatteryUsageStatsTest { final BatteryConsumer.Key cpuFgsKey = aggBuilder.getKey( BatteryConsumer.POWER_COMPONENT_CPU, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); + final BatteryConsumer.Key cpuCachedKey = aggBuilder.getKey( + BatteryConsumer.POWER_COMPONENT_CPU, + BatteryConsumer.PROCESS_STATE_CACHED); aggBuilder .setConsumedPower(cpuFgKey, cpuPowerForeground, BatteryConsumer.POWER_MODEL_POWER_PROFILE) @@ -415,7 +428,10 @@ public class BatteryUsageStatsTest { .setUsageDurationMillis(cpuBgKey, cpuDurationBackground) .setConsumedPower(cpuFgsKey, cpuPowerFgs, BatteryConsumer.POWER_MODEL_POWER_PROFILE) - .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs); + .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs) + .setConsumedPower(cpuCachedKey, cpuPowerCached, + BatteryConsumer.POWER_MODEL_POWER_PROFILE) + .setUsageDurationMillis(cpuCachedKey, cpuDurationCached); } } @@ -432,7 +448,7 @@ public class BatteryUsageStatsTest { 1000, 2000, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 500, 600, 800, - true, 1777, 1888, 1999, 1777, 7771, 1888, 8881, 1999, 9991); + true, 1777, 1888, 1999, 123, 1777, 7771, 1888, 8881, 1999, 9991, 123, 456); } else { fail("Unexpected UID " + uidBatteryConsumer.getUid()); } @@ -484,8 +500,10 @@ public class BatteryUsageStatsTest { int cpuPowerModel, double customComponentPower, int cpuDuration, int customComponentDuration, boolean processStateDataIncluded, double totalPowerForeground, double totalPowerBackground, double totalPowerFgs, - double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground, - int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs) { + double totalPowerCached, double cpuPowerForeground, int cpuDurationForeground, + double cpuPowerBackground, + int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs, + int cpuPowerCached, int cpuDurationCached) { assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(consumedPower); assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo( packageWithHighestDrain); @@ -525,6 +543,10 @@ public class BatteryUsageStatsTest { new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY, PROCESS_STATE_FOREGROUND_SERVICE))) .isEqualTo(totalPowerFgs); + assertThat(uidBatteryConsumer.getConsumedPower( + new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY, + PROCESS_STATE_CACHED))) + .isEqualTo(totalPowerCached); } final BatteryConsumer.Key cpuFgKey = uidBatteryConsumer.getKey( @@ -563,6 +585,19 @@ public class BatteryUsageStatsTest { } else { assertThat(cpuFgsKey).isNotNull(); } + + final BatteryConsumer.Key cachedKey = uidBatteryConsumer.getKey( + BatteryConsumer.POWER_COMPONENT_CPU, + BatteryConsumer.PROCESS_STATE_CACHED); + if (processStateDataIncluded) { + assertThat(cachedKey).isNotNull(); + assertThat(uidBatteryConsumer.getConsumedPower(cachedKey)) + .isEqualTo(cpuPowerCached); + assertThat(uidBatteryConsumer.getUsageDurationMillis(cachedKey)) + .isEqualTo(cpuDurationCached); + } else { + assertThat(cpuFgsKey).isNotNull(); + } } private void assertUserBatteryConsumer(UserBatteryConsumer userBatteryConsumer, diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java index 448f6664c2fa..fdbf071b7bba 100644 --- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java @@ -145,10 +145,14 @@ public class BluetoothPowerCalculatorTest { final BatteryConsumer.Key fgs = uidConsumer.getKey( BatteryConsumer.POWER_COMPONENT_BLUETOOTH, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); + final BatteryConsumer.Key cached = uidConsumer.getKey( + BatteryConsumer.POWER_COMPONENT_BLUETOOTH, + BatteryConsumer.PROCESS_STATE_CACHED); assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.081); assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.0416666); assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0); + assertThat(uidConsumer.getConsumedPower(cached)).isWithin(PRECISION).of(0); } @Test @@ -261,10 +265,14 @@ public class BluetoothPowerCalculatorTest { final BatteryConsumer.Key fgs = uidConsumer.getKey( BatteryConsumer.POWER_COMPONENT_BLUETOOTH, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); + final BatteryConsumer.Key cached = uidConsumer.getKey( + BatteryConsumer.POWER_COMPONENT_BLUETOOTH, + BatteryConsumer.PROCESS_STATE_CACHED); assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.4965352); assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.3255208); assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0); + assertThat(uidConsumer.getConsumedPower(cached)).isWithin(PRECISION).of(0); } diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java index b89e8bce5fc9..ec45a016507a 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -232,7 +232,7 @@ public final class LooperStatsTest { assertThat(entry3.handlerClassName).isEqualTo( "com.android.internal.os.LooperStatsTest$TestHandlerSecond"); assertThat(entry3.messageName).startsWith( - "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda4"); + "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda5"); assertThat(entry3.messageCount).isEqualTo(1); assertThat(entry3.recordedMessageCount).isEqualTo(1); assertThat(entry3.exceptionCount).isEqualTo(0); diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java index b659f37690a3..940ca96fac4f 100644 --- a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java @@ -19,14 +19,20 @@ package com.android.internal.util; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.UserInfo; @@ -50,6 +56,7 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; import java.nio.charset.StandardCharsets; +import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest @@ -164,6 +171,16 @@ public class LockPatternUtilsTest { verify(ils).isWeakEscrowTokenValid(eq(testHandle), eq(testToken), eq(testUserId)); } + @Test + public void testGetEnabledTrustAgentsNotNull() throws RemoteException { + int testUserId = 10; + ILockSettings ils = createTestLockSettings(); + when(ils.getString(anyString(), any(), anyInt())).thenReturn(""); + List<ComponentName> trustAgents = mLockPatternUtils.getEnabledTrustAgents(testUserId); + assertNotNull(trustAgents); + assertEquals(0, trustAgents.size()); + } + private ILockSettings createTestLockSettings() { final Context context = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); mLockPatternUtils = spy(new LockPatternUtils(context)); diff --git a/data/etc/com.android.launcher3.xml b/data/etc/com.android.launcher3.xml index 598d2027a0e9..36a51341f52d 100644 --- a/data/etc/com.android.launcher3.xml +++ b/data/etc/com.android.launcher3.xml @@ -16,6 +16,7 @@ --> <permissions> <privapp-permissions package="com.android.launcher3"> + <permission name="android.permission.ALLOW_SLIPPERY_TOUCHES"/> <permission name="android.permission.BIND_APPWIDGET"/> <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/> <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/> diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml index ae350ec547c3..2d1db716b700 100644 --- a/data/etc/com.android.systemui.xml +++ b/data/etc/com.android.systemui.xml @@ -17,6 +17,7 @@ <permissions> <privapp-permissions package="com.android.systemui"> <permission name="android.permission.CAPTURE_AUDIO_OUTPUT"/> + <permission name="android.permission.ALLOW_SLIPPERY_TOUCHES"/> <permission name="android.permission.BATTERY_STATS"/> <permission name="android.permission.BIND_APPWIDGET"/> <permission name="android.permission.BLUETOOTH_PRIVILEGED"/> @@ -75,5 +76,8 @@ <permission name="android.permission.FORCE_STOP_PACKAGES" /> <permission name="android.permission.ACCESS_FPS_COUNTER" /> <permission name="android.permission.CHANGE_CONFIGURATION" /> + <permission name="android.permission.LOG_COMPAT_CHANGE" /> + <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <permission name="android.permission.READ_DEVICE_CONFIG" /> </privapp-permissions> </permissions> diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 88920c865511..a8293397d7df 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -241,7 +241,7 @@ </split-permission> <split-permission name="android.permission.READ_EXTERNAL_STORAGE" targetSdk="33"> - <new-permission name="android.permission.READ_MEDIA_IMAGE" /> + <new-permission name="android.permission.READ_MEDIA_IMAGES" /> </split-permission> <split-permission name="android.permission.BLUETOOTH" targetSdk="31"> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index deffa3a6fea6..3e91eedf2dde 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -452,10 +452,11 @@ applications that come with the platform <permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" /> <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" /> <permission name="android.permission.NEARBY_WIFI_DEVICES" /> + <permission name="android.permission.MANAGE_WIFI_INTERFACES" /> <permission name="android.permission.OVERRIDE_WIFI_CONFIG" /> <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover - P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. --> - <permission name="android.permission.MANAGE_WIFI_AUTO_JOIN" /> + P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. --> + <permission name="android.permission.MANAGE_WIFI_NETWORK_SELECTION" /> <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest --> <permission name="android.permission.BIND_CARRIER_SERVICES"/> <!-- Permission required for CTS test - MusicRecognitionManagerTest --> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index df2b2a395ea7..e898f570a6b8 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1309,6 +1309,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "-711194343": { + "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "-706481945": { "message": "TaskFragment parent info changed name=%s parentTaskId=%d", "level": "VERBOSE", @@ -2587,6 +2593,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/WindowState.java" }, + "599897753": { + "message": "Previous Activity is %s. Back type is %s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "600140673": { "message": "checkBootAnimationComplete: Waiting for anim complete", "level": "INFO", @@ -2671,12 +2683,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "664667685": { - "message": "Activity %s: enableOnBackInvokedCallback=false. Returning null BackNavigationInfo.", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "665256544": { "message": "All windows drawn!", "level": "DEBUG", @@ -2887,6 +2893,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, + "948208142": { + "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "950074526": { "message": "setLockTaskMode: Can't lock due to auth", "level": "WARN", @@ -3103,6 +3115,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/DisplayContent.java" }, + "1172542963": { + "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "1178653181": { "message": "Old wallpaper still the target.", "level": "VERBOSE", @@ -3415,11 +3433,11 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "1554795024": { - "message": "Previous Activity is %s", + "1544805551": { + "message": "Skipping app transition animation. task=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "at": "com\/android\/server\/wm\/Task.java" }, "1557732761": { "message": "For Intent %s bringing to top: %s", diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 7e68bc06d506..1a522bd5e794 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -291,6 +291,14 @@ public final class Rect implements Parcelable { } /** + * @return {@code true} if the rectangle is valid (left <= right and top <= bottom). + * @hide + */ + public boolean isValid() { + return left <= right && top <= bottom; + } + + /** * @return the rectangle's width. This does not check for a valid rectangle * (i.e. left <= right) so the result may be negative. */ diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index ffaa4ea51452..c1addbf43937 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -1098,19 +1098,16 @@ public class RippleDrawable extends LayerDrawable { } // Draw the appropriate mask anchored to (0,0). + final int saveCount = mMaskCanvas.save(); final int left = bounds.left; final int top = bounds.top; - if (mState.mRippleStyle == STYLE_SOLID) { - mMaskCanvas.translate(-left, -top); - } + mMaskCanvas.translate(-left, -top); if (maskType == MASK_EXPLICIT) { drawMask(mMaskCanvas); } else if (maskType == MASK_CONTENT) { drawContent(mMaskCanvas); } - if (mState.mRippleStyle == STYLE_SOLID) { - mMaskCanvas.translate(left, top); - } + mMaskCanvas.restoreToCount(saveCount); if (mState.mRippleStyle == STYLE_PATTERNED) { for (int i = 0; i < mRunningAnimations.size(); i++) { mRunningAnimations.get(i).getProperties().getShader().setShader(mMaskShader); @@ -1210,9 +1207,13 @@ public class RippleDrawable extends LayerDrawable { updateMaskShaderIfNeeded(); // Position the shader to account for canvas translation. - if (mMaskShader != null && mState.mRippleStyle == STYLE_SOLID) { + if (mMaskShader != null) { final Rect bounds = getBounds(); - mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y); + if (mState.mRippleStyle == STYLE_PATTERNED) { + mMaskMatrix.setTranslate(bounds.left, bounds.top); + } else { + mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y); + } mMaskShader.setLocalMatrix(mMaskMatrix); } diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java index cffdf28dbc27..d083e444e996 100644 --- a/graphics/java/android/graphics/text/LineBreakConfig.java +++ b/graphics/java/android/graphics/text/LineBreakConfig.java @@ -26,7 +26,7 @@ import java.util.Objects; /** * Indicates the strategies can be used when calculating the text wrapping. * - * See <a href="https://drafts.csswg.org/css-text/#line-break-property">the line-break property</a> + * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">the line-break property</a> */ public final class LineBreakConfig { @@ -78,39 +78,96 @@ public final class LineBreakConfig { @Retention(RetentionPolicy.SOURCE) public @interface LineBreakWordStyle {} - private @LineBreakStyle int mLineBreakStyle = LINE_BREAK_STYLE_NONE; - private @LineBreakWordStyle int mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_NONE; - - public LineBreakConfig() { + /** + * A builder for creating {@link LineBreakConfig}. + */ + public static final class Builder { + // The line break style for the LineBreakConfig. + private @LineBreakStyle int mLineBreakStyle = LineBreakConfig.LINE_BREAK_STYLE_NONE; + + // The line break word style for the LineBreakConfig. + private @LineBreakWordStyle int mLineBreakWordStyle = + LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE; + + /** + * Builder constructor with line break parameters. + */ + public Builder() { + } + + /** + * Set the line break style. + * + * @param lineBreakStyle the new line break style. + * @return this Builder + */ + public @NonNull Builder setLineBreakStyle(@LineBreakStyle int lineBreakStyle) { + mLineBreakStyle = lineBreakStyle; + return this; + } + + /** + * Set the line break word style. + * + * @param lineBreakWordStyle the new line break word style. + * @return this Builder + */ + public @NonNull Builder setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) { + mLineBreakWordStyle = lineBreakWordStyle; + return this; + } + + /** + * Build the {@link LineBreakConfig} + * + * @return the LineBreakConfig instance. + */ + public @NonNull LineBreakConfig build() { + return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle); + } } /** - * Set the line break configuration. + * Create the LineBreakConfig instance. * - * @param lineBreakConfig the new line break configuration. + * @param lineBreakStyle the line break style for text wrapping. + * @param lineBreakWordStyle the line break word style for text wrapping. + * @return the {@link LineBreakConfig} instance. + * @hide */ - public void set(@NonNull LineBreakConfig lineBreakConfig) { - Objects.requireNonNull(lineBreakConfig); - mLineBreakStyle = lineBreakConfig.getLineBreakStyle(); - mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle(); + public static @NonNull LineBreakConfig getLineBreakConfig(@LineBreakStyle int lineBreakStyle, + @LineBreakWordStyle int lineBreakWordStyle) { + LineBreakConfig.Builder builder = new LineBreakConfig.Builder(); + return builder.setLineBreakStyle(lineBreakStyle) + .setLineBreakWordStyle(lineBreakWordStyle) + .build(); } + /** @hide */ + public static final LineBreakConfig NONE = + new Builder().setLineBreakStyle(LINE_BREAK_STYLE_NONE) + .setLineBreakWordStyle(LINE_BREAK_WORD_STYLE_NONE).build(); + + private final @LineBreakStyle int mLineBreakStyle; + private final @LineBreakWordStyle int mLineBreakWordStyle; + /** - * Get the line break style. - * - * @return The current line break style to be used for the text wrapping. + * Constructor with the line break parameters. + * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance. */ - public @LineBreakStyle int getLineBreakStyle() { - return mLineBreakStyle; + private LineBreakConfig(@LineBreakStyle int lineBreakStyle, + @LineBreakWordStyle int lineBreakWordStyle) { + mLineBreakStyle = lineBreakStyle; + mLineBreakWordStyle = lineBreakWordStyle; } /** - * Set the line break style. + * Get the line break style. * - * @param lineBreakStyle the new line break style. + * @return The current line break style to be used for the text wrapping. */ - public void setLineBreakStyle(@LineBreakStyle int lineBreakStyle) { - mLineBreakStyle = lineBreakStyle; + public @LineBreakStyle int getLineBreakStyle() { + return mLineBreakStyle; } /** @@ -122,15 +179,6 @@ public final class LineBreakConfig { return mLineBreakWordStyle; } - /** - * Set the line break word style. - * - * @param lineBreakWordStyle the new line break word style. - */ - public void setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) { - mLineBreakWordStyle = lineBreakWordStyle; - } - @Override public boolean equals(Object o) { if (o == null) return false; 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/OWNERS b/libs/WindowManager/OWNERS index 2c61df96eb03..780e4c1632f7 100644 --- a/libs/WindowManager/OWNERS +++ b/libs/WindowManager/OWNERS @@ -1,3 +1,6 @@ set noparent include /services/core/java/com/android/server/wm/OWNERS + +# Give submodule owners in shell resource approval +per-file Shell/res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com diff --git a/libs/WindowManager/Shell/res/values-land/styles.xml b/libs/WindowManager/Shell/res/values-land/styles.xml index 0ed9368aa067..e89f65bef792 100644 --- a/libs/WindowManager/Shell/res/values-land/styles.xml +++ b/libs/WindowManager/Shell/res/values-land/styles.xml @@ -16,7 +16,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="DockedDividerBackground"> - <item name="android:layout_width">10dp</item> + <item name="android:layout_width">@dimen/split_divider_bar_width</item> <item name="android:layout_height">match_parent</item> <item name="android:layout_gravity">center_horizontal</item> <item name="android:background">@color/split_divider_background</item> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 8d5fdfbc8cb0..08cb252cdf43 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -52,14 +52,17 @@ import com.android.wm.shell.common.annotations.ShellMainThread; */ public class BackAnimationController implements RemoteCallable<BackAnimationController> { - private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; - public static final boolean IS_ENABLED = SystemProperties - .getInt(BACK_PREDICTABILITY_PROP, 0) > 0; private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP = "persist.debug.back_predictability_progress_threshold"; + // By default, enable new back dispatching without any animations. + private static final int BACK_PREDICTABILITY_PROP = + SystemProperties.getInt("persist.debug.back_predictability", 1); + public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0; private static final int PROGRESS_THRESHOLD = SystemProperties .getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1); private static final String TAG = "BackAnimationController"; + @VisibleForTesting + boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0; /** * Location of the initial touch event of the back gesture. @@ -255,7 +258,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont backNavigationInfo.getTaskWindowConfiguration()); } mTransaction.apply(); - } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) { + } else if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; } else if (backType == BackNavigationInfo.TYPE_CALLBACK) { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); @@ -309,7 +312,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget); IOnBackInvokedCallback targetCallback = null; - if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) { + if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) { @@ -330,8 +333,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; } int backType = mBackNavigationInfo.getType(); - boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME - && mBackToLauncherCallback != null; + boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType); IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher ? mBackToLauncherCallback : mBackNavigationInfo.getOnBackInvokedCallback(); @@ -356,6 +358,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } + private boolean shouldDispatchToLauncher(int backType) { + return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME + && mBackToLauncherCallback != null + && mEnableAnimations; + } + + @VisibleForTesting + void setEnableAnimations(boolean shouldEnable) { + mEnableAnimations = shouldEnable; + } + private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) { if (callback == null) { return; @@ -468,7 +481,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; } RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget(); - if (animationTarget != null && mTriggerBack) { + if (animationTarget != null) { if (animationTarget.leash != null && animationTarget.leash.isValid()) { mTransaction.remove(animationTarget.leash); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index d0138a488295..d2a1c55d1c29 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -383,23 +383,15 @@ public class BubbleController { mTaskStackListener.addListener(new TaskStackListenerCallback() { @Override public void onTaskMovedToFront(int taskId) { - if (mSysuiProxy == null) { - return; - } - - mSysuiProxy.isNotificationShadeExpand((expand) -> { - mMainExecutor.execute(() -> { - int expandedId = INVALID_TASK_ID; - if (mStackView != null && mStackView.getExpandedBubble() != null - && isStackExpanded() && !mStackView.isExpansionAnimating() - && !expand) { - expandedId = mStackView.getExpandedBubble().getTaskId(); - } - - if (expandedId != INVALID_TASK_ID && expandedId != taskId) { - mBubbleData.setExpanded(false); - } - }); + mMainExecutor.execute(() -> { + int expandedId = INVALID_TASK_ID; + if (mStackView != null && mStackView.getExpandedBubble() != null + && isStackExpanded() && !mStackView.isExpansionAnimating()) { + expandedId = mStackView.getExpandedBubble().getTaskId(); + } + if (expandedId != INVALID_TASK_ID && expandedId != taskId) { + mBubbleData.setExpanded(false); + } }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index 51067a45381c..45833898e7c4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -344,7 +344,7 @@ public class SystemWindows { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration newMergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) {} + boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {} @Override public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index b52c8d118711..5246117486ed 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -98,6 +98,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange private WindowContainerToken mWinToken2; private int mDividePosition; private boolean mInitialized = false; + private boolean mFreezeDividerWindow = false; private int mOrientation; private int mRotation; @@ -225,11 +226,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null); initDividerPosition(mTempRect); - if (mInitialized) { - release(); - init(); - } - return true; } @@ -298,20 +294,37 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } /** Releases the surface holding the current {@link DividerView}. */ - public void release() { + public void release(SurfaceControl.Transaction t) { if (!mInitialized) return; mInitialized = false; - mSplitWindowManager.release(); + mSplitWindowManager.release(t); mDisplayImeController.removePositionProcessor(mImePositionProcessor); mImePositionProcessor.reset(); } + public void release() { + release(null /* t */); + } + + /** Releases and re-inflates {@link DividerView} on the root surface. */ + public void update(SurfaceControl.Transaction t) { + if (!mInitialized) return; + mSplitWindowManager.release(t); + mImePositionProcessor.reset(); + mSplitWindowManager.init(this, mInsetsState); + } + @Override public void insetsChanged(InsetsState insetsState) { mInsetsState.set(insetsState); if (!mInitialized) { return; } + if (mFreezeDividerWindow) { + // DO NOT change its layout before transition actually run because it might cause + // flicker. + return; + } mSplitWindowManager.onInsetsChanged(insetsState); } @@ -323,6 +336,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } } + public void setFreezeDividerWindow(boolean freezeDividerWindow) { + mFreezeDividerWindow = freezeDividerWindow; + } + /** * Updates bounds with the passing position. Usually used to update recording bounds while * performing animation or dragging divider bar to resize the splits. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java index 4903f9d46dc7..833d9d50701c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java @@ -58,6 +58,9 @@ public final class SplitWindowManager extends WindowlessWindowManager { private SurfaceControl mLeash; private DividerView mDividerView; + // Used to "pass" a transaction to WWM.remove so that view removal can be synchronized. + private SurfaceControl.Transaction mSyncTransaction = null; + public interface ParentContainerCallbacks { void attachToParentSurface(SurfaceControl.Builder b); void onLeashReady(SurfaceControl leash); @@ -130,22 +133,38 @@ public final class SplitWindowManager extends WindowlessWindowManager { * Releases the surface control of the current {@link DividerView} and tear down the view * hierarchy. */ - void release() { + void release(@Nullable SurfaceControl.Transaction t) { if (mDividerView != null) { mDividerView = null; } if (mViewHost != null){ + mSyncTransaction = t; mViewHost.release(); + mSyncTransaction = null; mViewHost = null; } if (mLeash != null) { - new SurfaceControl.Transaction().remove(mLeash).apply(); + if (t == null) { + new SurfaceControl.Transaction().remove(mLeash).apply(); + } else { + t.remove(mLeash); + } mLeash = null; } } + @Override + protected void removeSurface(SurfaceControl sc) { + // This gets called via SurfaceControlViewHost.release() + if (mSyncTransaction != null) { + mSyncTransaction.remove(sc); + } else { + super.removeSurface(sc); + } + } + void setInteractive(boolean interactive) { if (mDividerView == null) return; mDividerView.setInteractive(interactive); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index b266189ec262..c1e78251da2b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -18,7 +18,6 @@ package com.android.wm.shell.pip; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.util.RotationUtils.deltaRotation; import static android.util.RotationUtils.rotateBounds; @@ -450,11 +449,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height()); // We set to fullscreen here for now, but later it will be set to UNDEFINED for // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit. - wct.setActivityWindowingMode(mToken, - direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN - && !requestEnterSplit - ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY - : WINDOWING_MODE_FULLSCREEN); + wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN); wct.setBounds(mToken, destinationBounds); wct.setBoundsChangeTransaction(mToken, tx); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java index 3115f8afde3b..11633a91e8c6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java @@ -253,11 +253,11 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen private WindowManager.LayoutParams getDismissTargetLayoutParams() { final Point windowSize = new Point(); mWindowManager.getDefaultDisplay().getRealSize(windowSize); - + int height = Math.min(windowSize.y, mDismissAreaHeight); final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, - mDismissAreaHeight, - 0, windowSize.y - mDismissAreaHeight, + height, + 0, windowSize.y - height, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java index e57abc28bd0a..0f3ff36601fb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java @@ -148,6 +148,7 @@ public class PipInputConsumer { mMainExecutor.execute(() -> { // Choreographer.getSfInstance() must be called on the thread that the input event // receiver should be receiving events + // TODO(b/222697646): remove getSfInstance usage and use vsyncId for transactions mInputEventReceiver = new InputEventReceiver(inputChannel, Looper.myLooper(), Choreographer.getSfInstance()); if (mRegistrationListener != null) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index f3789fd5a3d6..fa0f0925a08a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -95,6 +95,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, final FrameCallbackScheduler scheduler = new FrameCallbackScheduler() { @Override public void postFrameCallback(@androidx.annotation.NonNull Runnable runnable) { + // TODO(b/222697646): remove getSfInstance usage and use vsyncId for + // transactions Choreographer.getSfInstance().postFrameCallback(t -> runnable.run()); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index c816f18c2fc2..abf1a9500e6d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -625,6 +625,7 @@ public class PipResizeGestureHandler { class PipResizeInputEventReceiver extends BatchedInputEventReceiver { PipResizeInputEventReceiver(InputChannel channel, Looper looper) { + // TODO(b/222697646): remove getSfInstance usage and use vsyncId for transactions super(channel, looper, Choreographer.getSfInstance()); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java index 72b934805c95..d6dacd14f536 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java @@ -30,17 +30,18 @@ import android.content.res.Resources; import android.graphics.Rect; import android.os.SystemClock; import android.util.ArraySet; -import android.util.Log; import android.util.Size; import android.view.Gravity; import androidx.annotation.NonNull; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.pip.PipBoundsAlgorithm; import com.android.wm.shell.pip.PipSnapAlgorithm; import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.Set; @@ -90,7 +91,10 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { /** Returns the destination bounds to place the PIP window on entry. */ @Override public Rect getEntryDestinationBounds() { - if (DEBUG) Log.d(TAG, "getEntryDestinationBounds()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: getEntryDestinationBounds()", TAG); + } if (mTvPipBoundsState.isTvExpandedPipSupported() && mTvPipBoundsState.getDesiredTvExpandedAspectRatio() != 0 && !mTvPipBoundsState.isTvPipManuallyCollapsed()) { @@ -104,7 +108,10 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { /** Returns the current bounds adjusted to the new aspect ratio, if valid. */ @Override public Rect getAdjustedDestinationBounds(Rect currentBounds, float newAspectRatio) { - if (DEBUG) Log.d(TAG, "getAdjustedDestinationBounds: " + newAspectRatio); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: getAdjustedDestinationBounds: %f", TAG, newAspectRatio); + } return getTvPipBounds().getBounds(); } @@ -122,7 +129,11 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { Set<Rect> unrestrictedKeepClearAreas = mTvPipBoundsState.getUnrestrictedKeepClearAreas(); if (mTvPipBoundsState.isImeShowing()) { - if (DEBUG) Log.d(TAG, "IME showing, height: " + mTvPipBoundsState.getImeHeight()); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: IME showing, height: %d", + TAG, mTvPipBoundsState.getImeHeight()); + } final Rect imeBounds = new Rect( 0, @@ -145,15 +156,22 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { unrestrictedKeepClearAreas); if (DEBUG) { - Log.d(TAG, "pipSize: " + pipSize); - Log.d(TAG, "screenSize: " + screenSize); - Log.d(TAG, "stashOffset: " + mTvPipBoundsState.getStashOffset()); - Log.d(TAG, "insetBounds: " + insetBounds.toShortString()); - Log.d(TAG, "pipSize: " + pipSize); - Log.d(TAG, "gravity: " + Gravity.toString(mTvPipBoundsState.getTvPipGravity())); - Log.d(TAG, "restrictedKeepClearAreas: " + restrictedKeepClearAreas); - Log.d(TAG, "unrestrictedKeepClearAreas: " + unrestrictedKeepClearAreas); - Log.d(TAG, "placement: " + placement); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: screenSize: %s", TAG, screenSize); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: stashOffset: %d", TAG, mTvPipBoundsState.getStashOffset()); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: insetBounds: %s", TAG, insetBounds.toShortString()); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: pipSize: %s", TAG, pipSize); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: gravity: %s", TAG, Gravity.toString(mTvPipBoundsState.getTvPipGravity())); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: restrictedKeepClearAreas: %s", TAG, restrictedKeepClearAreas); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: unrestrictedKeepClearAreas: %s", TAG, unrestrictedKeepClearAreas); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: placement: %s", TAG, placement); } return placement; @@ -164,9 +182,11 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { */ int updateGravityOnExpandToggled(int previousGravity, boolean expanding) { if (DEBUG) { - Log.d(TAG, "updateGravityOnExpandToggled(), expanding: " + expanding - + ", mOrientation: " + mTvPipBoundsState.getTvFixedPipOrientation() - + ", previous gravity: " + Gravity.toString(previousGravity)); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: updateGravityOnExpandToggled(), expanding: %b" + + ", mOrientation: %d, previous gravity: %s", + TAG, expanding, mTvPipBoundsState.getTvFixedPipOrientation(), + Gravity.toString(previousGravity)); } if (!mTvPipBoundsState.isTvExpandedPipSupported()) { @@ -218,7 +238,10 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { } } mTvPipBoundsState.setTvPipGravity(updatedGravity); - if (DEBUG) Log.d(TAG, "new gravity: " + Gravity.toString(updatedGravity)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: new gravity: %s", TAG, Gravity.toString(updatedGravity)); + } return gravityToSave; } @@ -227,7 +250,10 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { * @return true if gravity changed */ boolean updateGravity(int keycode) { - if (DEBUG) Log.d(TAG, "updateGravity, keycode: " + keycode); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: updateGravity, keycode: %d", TAG, keycode); + } // Check if position change is valid if (mTvPipBoundsState.isTvPipExpanded()) { @@ -284,7 +310,10 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { if (updatedGravity != currentGravity) { mTvPipBoundsState.setTvPipGravity(updatedGravity); - if (DEBUG) Log.d(TAG, "new gravity: " + Gravity.toString(updatedGravity)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: new gravity: %s", TAG, Gravity.toString(updatedGravity)); + } return true; } return false; @@ -313,7 +342,9 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { final Size expandedSize; if (expandedRatio == 0) { - Log.d(TAG, "updateExpandedPipSize(): Expanded mode aspect ratio of 0 not supported"); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: updateExpandedPipSize(): Expanded mode aspect ratio" + + " of 0 not supported", TAG); return; } else if (expandedRatio < 1) { // vertical @@ -324,10 +355,16 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { float aspectRatioHeight = mFixedExpandedWidthInPx / expandedRatio; if (maxHeight > aspectRatioHeight) { - if (DEBUG) Log.d(TAG, "Accommodate aspect ratio"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Accommodate aspect ratio", TAG); + } expandedSize = new Size(mFixedExpandedWidthInPx, (int) aspectRatioHeight); } else { - if (DEBUG) Log.d(TAG, "Aspect ratio is too extreme, use max size"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Aspect ratio is too extreme, use max size", TAG); + } expandedSize = new Size(mFixedExpandedWidthInPx, maxHeight); } } @@ -339,10 +376,16 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { int maxWidth = displayLayout.width() - (2 * mScreenEdgeInsets.x); float aspectRatioWidth = mFixedExpandedHeightInPx * expandedRatio; if (maxWidth > aspectRatioWidth) { - if (DEBUG) Log.d(TAG, "Accommodate aspect ratio"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Accommodate aspect ratio", TAG); + } expandedSize = new Size((int) aspectRatioWidth, mFixedExpandedHeightInPx); } else { - if (DEBUG) Log.d(TAG, "Aspect ratio is too extreme, use max size"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Aspect ratio is too extreme, use max size", TAG); + } expandedSize = new Size(maxWidth, mFixedExpandedHeightInPx); } } @@ -350,8 +393,9 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm { mTvPipBoundsState.setTvExpandedSize(expandedSize); if (DEBUG) { - Log.d(TAG, "updateExpandedPipSize(): expanded size, width=" + expandedSize.getWidth() - + ", height=" + expandedSize.getHeight()); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: updateExpandedPipSize(): expanded size, width: %d, height: %d", + TAG, expandedSize.getWidth(), expandedSize.getHeight()); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java index 03c5e98de298..f397ac01e60d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java @@ -32,9 +32,9 @@ import android.content.res.Resources; import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; -import android.util.Log; import android.view.Gravity; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.common.DisplayController; @@ -50,6 +50,7 @@ import com.android.wm.shell.pip.PipMediaController; import com.android.wm.shell.pip.PipTaskOrganizer; import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -182,10 +183,16 @@ public class TvPipController implements PipTransitionController.PipTransitionCal } private void onConfigurationChanged(Configuration newConfig) { - if (DEBUG) Log.d(TAG, "onConfigurationChanged(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onConfigurationChanged(), state=%s", TAG, stateToName(mState)); + } if (isPipShown()) { - if (DEBUG) Log.d(TAG, " > closing Pip."); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: > closing Pip.", TAG); + } closePip(); } @@ -208,10 +215,16 @@ public class TvPipController implements PipTransitionController.PipTransitionCal */ @Override public void showPictureInPictureMenu() { - if (DEBUG) Log.d(TAG, "showPictureInPictureMenu(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: showPictureInPictureMenu(), state=%s", TAG, stateToName(mState)); + } if (mState == STATE_NO_PIP) { - if (DEBUG) Log.d(TAG, " > cannot open Menu from the current state."); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: > cannot open Menu from the current state.", TAG); + } return; } @@ -221,7 +234,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void closeMenu() { - if (DEBUG) Log.d(TAG, "closeMenu(), state before=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: closeMenu(), state before=%s", TAG, stateToName(mState)); + } setState(STATE_PIP); mTvPipBoundsAlgorithm.keepUnstashedForCurrentKeepClearAreas(); updatePinnedStackBounds(); @@ -237,7 +253,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal */ @Override public void movePipToFullscreen() { - if (DEBUG) Log.d(TAG, "movePipToFullscreen(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: movePipToFullscreen(), state=%s", TAG, stateToName(mState)); + } mPipTaskOrganizer.exitPip(mResizeAnimationDuration, false /* requestEnterSplit */); onPipDisappeared(); @@ -245,7 +264,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void togglePipExpansion() { - if (DEBUG) Log.d(TAG, "togglePipExpansion()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: togglePipExpansion()", TAG); + } boolean expanding = !mTvPipBoundsState.isTvPipExpanded(); int saveGravity = mTvPipBoundsAlgorithm .updateGravityOnExpandToggled(mPreviousGravity, expanding); @@ -264,7 +286,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal mPreviousGravity = Gravity.NO_GRAVITY; updatePinnedStackBounds(); } else { - if (DEBUG) Log.d(TAG, "Position hasn't changed"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Position hasn't changed", TAG); + } } } @@ -323,10 +348,16 @@ public class TvPipController implements PipTransitionController.PipTransitionCal /** Animates the PiP to the given bounds. */ private void movePinnedStackTo(Rect bounds) { - if (DEBUG) Log.d(TAG, "movePinnedStackTo() - new pip bounds: " + bounds.toShortString()); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: movePinnedStack() - new pip bounds: %s", TAG, bounds.toShortString()); + } mPipTaskOrganizer.scheduleAnimateResizePip(bounds, mResizeAnimationDuration, rect -> { - if (DEBUG) Log.d(TAG, "movePinnedStack() animation done"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: movePinnedStack() animation done", TAG); + } mTvPipMenuController.updateExpansionState(); }); } @@ -336,7 +367,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal */ @Override public void closePip() { - if (DEBUG) Log.d(TAG, "closePip(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: closePip(), state=%s", TAG, stateToName(mState)); + } removeTask(mPinnedTaskId); onPipDisappeared(); @@ -348,7 +382,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private void checkIfPinnedTaskAppeared() { final TaskInfo pinnedTask = getPinnedTaskInfo(); - if (DEBUG) Log.d(TAG, "checkIfPinnedTaskAppeared(), task=" + pinnedTask); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: checkIfPinnedTaskAppeared(), task=%s", TAG, pinnedTask); + } if (pinnedTask == null || pinnedTask.topActivity == null) return; mPinnedTaskId = pinnedTask.taskId; @@ -357,16 +394,23 @@ public class TvPipController implements PipTransitionController.PipTransitionCal } private void checkIfPinnedTaskIsGone() { - if (DEBUG) Log.d(TAG, "onTaskStackChanged()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onTaskStackChanged()", TAG); + } if (isPipShown() && getPinnedTaskInfo() == null) { - Log.w(TAG, "Pinned task is gone."); + ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Pinned task is gone.", TAG); onPipDisappeared(); } } private void onPipDisappeared() { - if (DEBUG) Log.d(TAG, "onPipDisappeared() state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onPipDisappeared() state=%s", TAG, stateToName(mState)); + } mPipNotificationController.dismiss(); mTvPipMenuController.hideMenu(); @@ -377,12 +421,18 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void onPipTransitionStarted(int direction, Rect pipBounds) { - if (DEBUG) Log.d(TAG, "onPipTransition_Started(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onPipTransition_Started(), state=%s", TAG, stateToName(mState)); + } } @Override public void onPipTransitionCanceled(int direction) { - if (DEBUG) Log.d(TAG, "onPipTransition_Canceled(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onPipTransition_Canceled(), state=%s", TAG, stateToName(mState)); + } } @Override @@ -390,18 +440,25 @@ public class TvPipController implements PipTransitionController.PipTransitionCal if (PipAnimationController.isInPipDirection(direction) && mState == STATE_NO_PIP) { setState(STATE_PIP); } - if (DEBUG) Log.d(TAG, "onPipTransition_Finished(), state=" + stateToName(mState)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onPipTransition_Finished(), state=%s", TAG, stateToName(mState)); + } } private void setState(@State int state) { if (DEBUG) { - Log.d(TAG, "setState(), state=" + stateToName(state) + ", prev=" - + stateToName(mState)); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: setState(), state=%s, prev=%s", + TAG, stateToName(state), stateToName(mState)); } mState = state; if (mState == STATE_PIP_MENU) { - if (DEBUG) Log.d(TAG, " > show menu"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: > show menu", TAG); + } mTvPipMenuController.showMenu(); } @@ -429,7 +486,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { if (task.getWindowingMode() == WINDOWING_MODE_PINNED) { - if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onPinnedActivityRestartAttempt()", TAG); + } // If the "Pip-ed" Activity is launched again by Launcher or intent, make it // fullscreen. @@ -445,8 +505,9 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { if (DEBUG) { - Log.d(TAG, "onImeVisibilityChanged(), visible=" + imeVisible - + ", height=" + imeHeight); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onImeVisibilityChanged(), visible=%b, height=%d", + TAG, imeVisible, imeHeight); } if (imeVisible == mTvPipBoundsState.isImeShowing() @@ -464,7 +525,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void onAspectRatioChanged(float ratio) { - if (DEBUG) Log.d(TAG, "onAspectRatioChanged: " + ratio); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onAspectRatioChanged: %f", TAG, ratio); + } boolean ratioChanged = mTvPipBoundsState.getAspectRatio() != ratio; mTvPipBoundsState.setAspectRatio(ratio); @@ -476,7 +540,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void onExpandedAspectRatioChanged(float ratio) { - if (DEBUG) Log.d(TAG, "onExpandedAspectRatioChanged: " + ratio); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onExpandedAspectRatioChanged: %f", TAG, ratio); + } // 0) No update to the ratio --> don't do anything @@ -526,35 +593,50 @@ public class TvPipController implements PipTransitionController.PipTransitionCal @Override public void onActionsChanged(ParceledListSlice<RemoteAction> actions) { - if (DEBUG) Log.d(TAG, "onActionsChanged()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onActionsChanged()", TAG); + } mTvPipMenuController.setAppActions(actions); } }); } catch (RemoteException e) { - Log.e(TAG, "Failed to register pinned stack listener", e); + ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Failed to register pinned stack listener, %s", TAG, e); } } private static TaskInfo getPinnedTaskInfo() { - if (DEBUG) Log.d(TAG, "getPinnedTaskInfo()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: getPinnedTaskInfo()", TAG); + } try { final TaskInfo taskInfo = ActivityTaskManager.getService().getRootTaskInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); - if (DEBUG) Log.d(TAG, " > taskInfo=" + taskInfo); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: > taskInfo=%s", TAG, taskInfo); + } return taskInfo; } catch (RemoteException e) { - Log.e(TAG, "getRootTaskInfo() failed", e); + ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: getRootTaskInfo() failed, %s", TAG, e); return null; } } private static void removeTask(int taskId) { - if (DEBUG) Log.d(TAG, "removeTask(), taskId=" + taskId); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: removeTask(), taskId=%d", TAG, taskId); + } try { ActivityTaskManager.getService().removeTask(taskId); } catch (Exception e) { - Log.e(TAG, "Atm.removeTask() failed", e); + ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Atm.removeTask() failed, %s", TAG, e); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java index b3c230683cb3..1a035c5a68db 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java @@ -30,17 +30,18 @@ import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; import android.os.RemoteException; -import android.util.Log; import android.view.SurfaceControl; import android.view.SyncRtSurfaceTransactionApplier; import android.view.WindowManagerGlobal; import androidx.annotation.Nullable; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.pip.PipMediaController; import com.android.wm.shell.pip.PipMenuController; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.ArrayList; import java.util.List; @@ -110,7 +111,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } void setDelegate(Delegate delegate) { - if (DEBUG) Log.d(TAG, "setDelegate(), delegate=" + delegate); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: setDelegate(), delegate=%s", TAG, delegate); + } if (mDelegate != null) { throw new IllegalStateException( "The delegate has already been set and should not change."); @@ -133,7 +137,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } private void attachPipMenuView() { - if (DEBUG) Log.d(TAG, "attachPipMenuView()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: attachPipMenuView()", TAG); + } if (mPipMenuView != null) { detachPipMenuView(); @@ -148,7 +155,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public void showMenu() { - if (DEBUG) Log.d(TAG, "showMenu()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: showMenu()", TAG); + } if (mPipMenuView != null) { Rect menuBounds = getMenuBounds(mTvPipBoundsState.getBounds()); @@ -189,10 +199,16 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis void hideMenu() { if (!isMenuVisible()) { - if (DEBUG) Log.d(TAG, "hideMenu() - Menu isn't visible, so don't hide"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: hideMenu() - Menu isn't visible, so don't hide", TAG); + } return; } else { - if (DEBUG) Log.d(TAG, "hideMenu()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: hideMenu()", TAG); + } } mPipMenuView.hide(); @@ -208,7 +224,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public void onEnterMoveMode() { - if (DEBUG) Log.d(TAG, "onEnterMoveMode - " + mInMoveMode); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onEnterMoveMode - %b", TAG, mInMoveMode); + } mInMoveMode = true; mPipMenuView.showMenuButtons(false); mPipMenuView.showMovementHints(mDelegate.getPipGravity()); @@ -217,7 +236,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public boolean onExitMoveMode() { - if (DEBUG) Log.d(TAG, "onExitMoveMode - " + mInMoveMode); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onExitMoveMode - %b", TAG, mInMoveMode); + } if (mInMoveMode) { mInMoveMode = false; mPipMenuView.showMenuButtons(true); @@ -230,7 +252,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public boolean onPipMovement(int keycode) { - if (DEBUG) Log.d(TAG, "onPipMovement - " + mInMoveMode); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onPipMovement - %b", TAG, mInMoveMode); + } if (mInMoveMode) { mDelegate.movePip(keycode); } @@ -246,12 +271,18 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public void setAppActions(ParceledListSlice<RemoteAction> actions) { - if (DEBUG) Log.d(TAG, "setAppActions()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: setAppActions()", TAG); + } updateAdditionalActionsList(mAppActions, actions.getList()); } private void onMediaActionsChanged(List<RemoteAction> actions) { - if (DEBUG) Log.d(TAG, "onMediaActionsChanged()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: onMediaActionsChanged()", TAG); + } // Hide disabled actions. List<RemoteAction> enabledActions = new ArrayList<>(); @@ -292,7 +323,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public boolean isMenuVisible() { boolean isVisible = mPipMenuView != null && mPipMenuView.isVisible(); - if (DEBUG) Log.d(TAG, "isMenuVisible: " + isVisible); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: isMenuVisible: %b", TAG, isVisible); + } return isVisible; } @@ -303,7 +337,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis public void resizePipMenu(@android.annotation.Nullable SurfaceControl pipLeash, @android.annotation.Nullable SurfaceControl.Transaction t, Rect destinationBounds) { - if (DEBUG) Log.d(TAG, "resizePipMenu: " + destinationBounds.toShortString()); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: resizePipMenu: %s", TAG, destinationBounds.toShortString()); + } if (destinationBounds.isEmpty()) { return; } @@ -335,10 +372,16 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction, Rect pipDestBounds) { - if (DEBUG) Log.d(TAG, "movePipMenu: " + pipDestBounds.toShortString()); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: movePipMenu: %s", TAG, pipDestBounds.toShortString()); + } if (pipDestBounds.isEmpty()) { - if (transaction == null && DEBUG) Log.d(TAG, "no transaction given"); + if (transaction == null && DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: no transaction given", TAG); + } return; } if (!maybeCreateSyncApplier()) { @@ -351,10 +394,16 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis // resizing and the PiP menu is also resized. We then want to do a scale from the current // new menu bounds. if (pipLeash != null && transaction != null) { - if (DEBUG) Log.d(TAG, "mTmpSourceBounds based on mPipMenuView.getBoundsOnScreen()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: mTmpSourceBounds based on mPipMenuView.getBoundsOnScreen()", TAG); + } mPipMenuView.getBoundsOnScreen(mTmpSourceBounds); } else { - if (DEBUG) Log.d(TAG, "mTmpSourceBounds based on menu width and height"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: mTmpSourceBounds based on menu width and height", TAG); + } mTmpSourceBounds.set(0, 0, menuDestBounds.width(), menuDestBounds.height()); } @@ -389,7 +438,8 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis private boolean maybeCreateSyncApplier() { if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) { - Log.v(TAG, "Not going to move PiP, either menu or its parent is not created."); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Not going to move PiP, either menu or its parent is not created.", TAG); return false; } @@ -412,7 +462,10 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public void updateMenuBounds(Rect destinationBounds) { Rect menuBounds = getMenuBounds(destinationBounds); - if (DEBUG) Log.d(TAG, "updateMenuBounds: " + menuBounds.toShortString()); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: updateMenuBounds: %s", TAG, menuBounds.toShortString()); + } mSystemWindows.updateViewLayout(mPipMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE, menuBounds.width(), menuBounds.height())); @@ -423,7 +476,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis @Override public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { - Log.d(TAG, "onFocusTaskChanged"); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: onFocusTaskChanged", TAG); } @Override @@ -465,13 +518,17 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } private void grantPipMenuFocus(boolean grantFocus) { - if (DEBUG) Log.d(TAG, "grantWindowFocus(" + grantFocus + ")"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: grantWindowFocus(%b)", TAG, grantFocus); + } try { WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */, mSystemWindows.getFocusGrantToken(mPipMenuView), grantFocus); } catch (Exception e) { - Log.e(TAG, "Unable to update focus", e); + ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Unable to update focus, %s", TAG, e); } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java index 3090139f6db9..984dea2c016e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java @@ -31,7 +31,6 @@ import android.content.Context; import android.graphics.Rect; import android.os.Handler; import android.util.AttributeSet; -import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.SurfaceControl; @@ -45,7 +44,9 @@ import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.ArrayList; import java.util.List; @@ -118,17 +119,24 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { } void updateLayout(Rect updatedBounds) { - Log.d(TAG, "update menu layout: " + updatedBounds.toShortString()); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: update menu layout: %s", TAG, updatedBounds.toShortString()); boolean previouslyVertical = mCurrentBounds != null && mCurrentBounds.height() > mCurrentBounds.width(); boolean vertical = updatedBounds.height() > updatedBounds.width(); mCurrentBounds = updatedBounds; if (previouslyVertical == vertical) { - if (DEBUG) Log.d(TAG, "no update for menu layout"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: no update for menu layout", TAG); + } return; } else { - if (DEBUG) Log.d(TAG, "change menu layout to vertical: " + vertical); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: change menu layout to vertical: %b", TAG, vertical); + } } if (vertical) { @@ -154,7 +162,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { } void setIsExpanded(boolean expanded) { - if (DEBUG) Log.d(TAG, "setIsExpanded, expanded: " + expanded); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: setIsExpanded, expanded: %b", TAG, expanded); + } mExpandButton.setImageResource( expanded ? R.drawable.pip_ic_collapse : R.drawable.pip_ic_expand); mExpandButton.setTextAndDescription( @@ -162,7 +173,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { } void show(boolean inMoveMode, int gravity) { - if (DEBUG) Log.d(TAG, "show(), inMoveMode: " + inMoveMode); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: show(), inMoveMode: %b", TAG, inMoveMode); + } if (inMoveMode) { showMovementHints(gravity); } else { @@ -172,7 +186,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { } void hide() { - if (DEBUG) Log.d(TAG, "hide()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: hide()", TAG); + } animateAlphaTo(0, mActionButtonsContainer); animateAlphaTo(0, mMenuFrameView); hideMovementHints(); @@ -205,7 +221,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { } void setAdditionalActions(List<RemoteAction> actions, Handler mainHandler) { - if (DEBUG) Log.d(TAG, "setAdditionalActions()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: setAdditionalActions()", TAG); + } // Make sure we exactly as many additional buttons as we have actions to display. final int actionsNumber = actions.size(); @@ -278,10 +297,12 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { try { action.getActionIntent().send(); } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "Failed to send action", e); + ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Failed to send action, %s", TAG, e); } } else { - Log.w(TAG, "RemoteAction is null"); + ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: RemoteAction is null", TAG); } } } @@ -289,8 +310,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { @Override public boolean dispatchKeyEvent(KeyEvent event) { if (DEBUG) { - Log.d(TAG, "dispatchKeyEvent, action: " + event.getAction() - + ", keycode: " + event.getKeyCode()); + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: dispatchKeyEvent, action: %d, keycode: %d", + TAG, event.getAction(), event.getKeyCode()); } if (mListener != null && event.getAction() == ACTION_UP) { switch (event.getKeyCode()) { @@ -317,7 +339,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { * Shows user hints for moving the PiP, e.g. arrows. */ public void showMovementHints(int gravity) { - if (DEBUG) Log.d(TAG, "showMovementHints(), position: " + Gravity.toString(gravity)); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: showMovementHints(), position: %s", TAG, Gravity.toString(gravity)); + } animateAlphaTo(checkGravity(gravity, Gravity.BOTTOM) ? 1f : 0f, mArrowUp); animateAlphaTo(checkGravity(gravity, Gravity.TOP) ? 1f : 0f, mArrowDown); @@ -333,7 +358,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { * Hides user hints for moving the PiP, e.g. arrows. */ public void hideMovementHints() { - if (DEBUG) Log.d(TAG, "hideMovementHints()"); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: hideMovementHints()", TAG); + } animateAlphaTo(0, mArrowUp); animateAlphaTo(0, mArrowRight); animateAlphaTo(0, mArrowDown); @@ -344,7 +372,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { * Show or hide the pip user actions. */ public void showMenuButtons(boolean show) { - if (DEBUG) Log.d(TAG, "showMenuButtons: " + show); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: showMenuButtons: %b", TAG, show); + } animateAlphaTo(show ? 1 : 0, mActionButtonsContainer); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java index dd7e29451ffc..7bd3ce9c45b2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java @@ -28,13 +28,13 @@ import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.media.MediaMetadata; import android.os.Handler; -import android.os.UserHandle; import android.text.TextUtils; -import android.util.Log; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.pip.PipMediaController; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.Objects; @@ -98,7 +98,10 @@ public class TvPipNotificationController { } void setDelegate(Delegate delegate) { - if (DEBUG) Log.d(TAG, "setDelegate(), delegate=" + delegate); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: setDelegate(), delegate=%s", TAG, delegate); + } if (mDelegate != null) { throw new IllegalStateException( "The delegate has already been set and should not change."); @@ -240,7 +243,10 @@ public class TvPipNotificationController { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); - if (DEBUG) Log.d(TAG, "on(Broadcast)Receive(), action=" + action); + if (DEBUG) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: on(Broadcast)Receive(), action=%s", TAG, action); + } if (ACTION_SHOW_PIP_MENU.equals(action)) { mDelegate.showPictureInPictureMenu(); 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..ec1ddf077795 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 @@ -29,6 +29,7 @@ import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.transitTypeToString; import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER; +import static android.window.TransitionInfo.FLAG_IS_DISPLAY; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; @@ -1171,6 +1172,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, updateUnfoldBounds(); return; } + + mSplitLayout.update(null /* t */); onLayoutSizeChanged(mSplitLayout); } } @@ -1198,7 +1201,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (!ENABLE_SHELL_TRANSITIONS) return; final SurfaceControl.Transaction t = mTransactionPool.acquire(); - setDividerVisibility(false, t); mDisplayLayout.rotateTo(mContext.getResources(), toRotation); mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets()); updateWindowBounds(mSplitLayout, wct); @@ -1255,8 +1257,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable TransitionRequestInfo request) { final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); if (triggerTask == null) { - // Still want to monitor everything while in split-screen, so return non-null. - return mMainStage.isActive() ? new WindowContainerTransaction() : null; + if (mMainStage.isActive()) { + if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) { + mSplitLayout.setFreezeDividerWindow(true); + } + // Still want to monitor everything while in split-screen, so return non-null. + return new WindowContainerTransaction(); + } else { + return null; + } } else if (triggerTask.displayId != mDisplayId) { // Skip handling task on the other display. return null; @@ -1329,8 +1338,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); } } @@ -1349,8 +1361,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, // If we're not in split-mode, just abort so something else can handle it. if (!mMainStage.isActive()) return false; + mSplitLayout.setFreezeDividerWindow(false); for (int iC = 0; iC < info.getChanges().size(); ++iC) { final TransitionInfo.Change change = info.getChanges().get(iC); + if (change.getMode() == TRANSIT_CHANGE + && (change.getFlags() & FLAG_IS_DISPLAY) != 0) { + mSplitLayout.update(startTransaction); + } + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null || !taskInfo.hasParentTask()) continue; final StageTaskListener stage = getStageOfTask(taskInfo); @@ -1365,10 +1383,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called" + " with " + taskInfo.taskId + " before startAnimation()."); } - } else if (info.getType() == TRANSIT_CHANGE - && change.getStartRotation() != change.getEndRotation()) { - // Show the divider after transition finished. - setDividerVisibility(true, finishTransaction); } } if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index 1bef552e57ca..49f907b0a8ca 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -62,6 +62,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.HardwareBuffer; +import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; @@ -243,7 +244,7 @@ public class TaskSnapshotWindow { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout"); session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState, - tmpControls); + tmpControls, new Bundle()); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } catch (RemoteException e) { snapshotSurface.clearWindowSynced(); @@ -517,7 +518,7 @@ public class TaskSnapshotWindow { private void reportDrawn() { try { - mSession.finishDrawing(mWindow, null /* postDrawTransaction */); + mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE); } catch (RemoteException e) { clearWindowSynced(); } @@ -534,7 +535,7 @@ public class TaskSnapshotWindow { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId) { if (mOuter != null) { mOuter.mSplashScreenExecutor.execute(() -> { if (mergedConfiguration != null diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt index 61e27f21aa0f..fb404b913465 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.flicker.bubble +import android.platform.test.annotations.Presubmit import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import androidx.test.uiautomator.By @@ -24,6 +25,8 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.annotation.Group4 import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled +import org.junit.Assume import org.junit.runner.RunWith import org.junit.Test import org.junit.runners.Parameterized @@ -69,9 +72,19 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr } } - @FlakyTest + @Presubmit @Test fun testAppIsVisibleAtEnd() { + Assume.assumeFalse(isShellTransitionsEnabled) + testSpec.assertLayersEnd { + this.isVisible(testApp.component) + } + } + + @FlakyTest + @Test + fun testAppIsVisibleAtEnd_ShellTransit() { + Assume.assumeTrue(isShellTransitionsEnabled) testSpec.assertLayersEnd { this.isVisible(testApp.component) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt index a57d3e63b559..c43230e77683 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.flicker.bubble +import android.platform.test.annotations.Presubmit import androidx.test.filters.FlakyTest import android.platform.test.annotations.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory @@ -57,9 +58,19 @@ open class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen } } - @FlakyTest(bugId = 218642026) + @Presubmit @Test open fun testAppIsAlwaysVisible() { + Assume.assumeFalse(isShellTransitionsEnabled) + testSpec.assertLayers { + this.isVisible(testApp.component) + } + } + + @FlakyTest(bugId = 218642026) + @Test + open fun testAppIsAlwaysVisible_ShellTransit() { + Assume.assumeTrue(isShellTransitionsEnabled) testSpec.assertLayers { this.isVisible(testApp.component) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index 905468514a65..3e7ee25da5f8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -78,6 +78,7 @@ public class BackAnimationControllerTest { MockitoAnnotations.initMocks(this); mController = new BackAnimationController( mShellExecutor, mTransaction, mActivityTaskManager, mContext); + mController.setEnableAnimations(true); } private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java index 9bb54a18063f..2e5078d86a8b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java @@ -61,7 +61,7 @@ public class SplitWindowManagerTests extends ShellTestCase { public void testInitRelease() { mSplitWindowManager.init(mSplitLayout, new InsetsState()); assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull(); - mSplitWindowManager.release(); + mSplitWindowManager.release(null /* t */); assertThat(mSplitWindowManager.getSurfaceControl()).isNull(); } } diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index 63b831de5da1..c80fb188e70f 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -118,7 +118,7 @@ cc_library { "libz", ], }, - linux_glibc: { + host_linux: { srcs: [ "CursorWindow.cpp", ], diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index bcfe9c3ecab4..30ca7d155c4c 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -135,7 +135,7 @@ bool Properties::load() { skpCaptureEnabled = debuggingEnabled && base::GetBoolProperty(PROPERTY_CAPTURE_SKP_ENABLED, false); SkAndroidFrameworkTraceUtil::setEnableTracing( - base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false)); + base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, true)); runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false); diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp index 055dbb2b5c5e..99508a2943ff 100644 --- a/libs/storage/IMountService.cpp +++ b/libs/storage/IMountService.cpp @@ -48,8 +48,6 @@ enum { TRANSACTION_isObbMounted, TRANSACTION_getMountedObbPath, TRANSACTION_isExternalStorageEmulated, - TRANSACTION_decryptStorage, - TRANSACTION_encryptStorage, }; class BpMountService: public BpInterface<IMountService> @@ -517,40 +515,6 @@ public: path = reply.readString16(); return true; } - - int32_t decryptStorage(const String16& password) - { - Parcel data, reply; - data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); - data.writeString16(password); - if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) { - ALOGD("decryptStorage could not contact remote\n"); - return -1; - } - int32_t err = reply.readExceptionCode(); - if (err < 0) { - ALOGD("decryptStorage caught exception %d\n", err); - return err; - } - return reply.readInt32(); - } - - int32_t encryptStorage(const String16& password) - { - Parcel data, reply; - data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); - data.writeString16(password); - if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) { - ALOGD("encryptStorage could not contact remote\n"); - return -1; - } - int32_t err = reply.readExceptionCode(); - if (err < 0) { - ALOGD("encryptStorage caught exception %d\n", err); - return err; - } - return reply.readInt32(); - } }; IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IStorageManager") diff --git a/libs/storage/include/storage/IMountService.h b/libs/storage/include/storage/IMountService.h index 5b07318f4432..5a9c39bc021b 100644 --- a/libs/storage/include/storage/IMountService.h +++ b/libs/storage/include/storage/IMountService.h @@ -70,8 +70,6 @@ public: const sp<IObbActionListener>& token, const int32_t nonce) = 0; virtual bool isObbMounted(const String16& filename) = 0; virtual bool getMountedObbPath(const String16& filename, String16& path) = 0; - virtual int32_t decryptStorage(const String16& password) = 0; - virtual int32_t encryptStorage(const String16& password) = 0; }; // ---------------------------------------------------------------------------- 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..9eb4a6c393ab 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -626,6 +626,7 @@ public final class TvInteractiveAppManager { /** * This is called when the state of the interactive app service is changed. * + * @param iAppServiceId The ID of the TV Interactive App service. * @param type the interactive app type * @param state the current state of the service of the given type * @param err the error code for error state. {@link #ERROR_NONE} is used when the state is @@ -760,7 +761,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 +778,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) { @@ -805,8 +816,8 @@ public final class TvInteractiveAppManager { * @param executor A {@link Executor} that the status change will be delivered to. */ public void registerCallback( - @NonNull TvInteractiveAppCallback callback, - @CallbackExecutor @NonNull Executor executor) { + @CallbackExecutor @NonNull Executor executor, + @NonNull TvInteractiveAppCallback callback) { Preconditions.checkNotNull(callback); Preconditions.checkNotNull(executor); synchronized (mLock) { @@ -1813,8 +1824,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..d22fd83872e1 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -16,9 +16,11 @@ package android.media.tv.interactive; +import android.annotation.CallSuper; 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 +78,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 +245,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) { } @@ -351,6 +352,7 @@ public abstract class TvInteractiveAppService extends Service { * @param enable {@code true} if you want to enable the media view. {@code false} * otherwise. */ + @CallSuper public void setMediaViewEnabled(final boolean enable) { mHandler.post(new Runnable() { @Override @@ -383,7 +385,7 @@ public abstract class TvInteractiveAppService extends Service { } /** - * Resets TvIAppService session. + * Resets TvInteractiveAppService session. */ public void onResetInteractiveApp() { } @@ -467,11 +469,11 @@ public abstract class TvInteractiveAppService extends Service { * in {@link #onSetSurface}. This method is always called at least once, after * {@link #onSetSurface} is called with non-null surface. * - * @param format The new PixelFormat of the surface. + * @param format The new {@link PixelFormat} of the surface. * @param width The new width of the surface. * @param height The new height of the surface. */ - public void onSurfaceChanged(int format, int width, int height) { + public void onSurfaceChanged(@PixelFormat.Format int format, int width, int height) { } /** @@ -631,6 +633,7 @@ public abstract class TvInteractiveAppService extends Service { * @param right Right position in pixels, relative to the overlay view. * @param bottom Bottom position in pixels, relative to the overlay view. */ + @CallSuper public void layoutSurface(final int left, final int top, final int right, final int bottom) { if (left > right || top > bottom) { @@ -659,6 +662,7 @@ public abstract class TvInteractiveAppService extends Service { * Requests broadcast related information from the related TV input. * @param request the request for broadcast info */ + @CallSuper public void requestBroadcastInfo(@NonNull final BroadcastInfoRequest request) { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -683,6 +687,7 @@ public abstract class TvInteractiveAppService extends Service { * Remove broadcast information request from the related TV input. * @param requestId the ID of the request */ + @CallSuper public void removeBroadcastInfo(final int requestId) { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -709,6 +714,7 @@ public abstract class TvInteractiveAppService extends Service { * @param cmdType type of the specific command * @param parameters parameters of the specific command */ + @CallSuper public void sendPlaybackCommandRequest( @PlaybackCommandType @NonNull String cmdType, @Nullable Bundle parameters) { executeOrPostRunnableOnMainThread(new Runnable() { @@ -733,6 +739,7 @@ public abstract class TvInteractiveAppService extends Service { /** * Sets broadcast video bounds. */ + @CallSuper public void setVideoBounds(@NonNull Rect rect) { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -755,6 +762,7 @@ public abstract class TvInteractiveAppService extends Service { /** * Requests the URI of the current channel. */ + @CallSuper public void requestCurrentChannelUri() { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -777,6 +785,7 @@ public abstract class TvInteractiveAppService extends Service { /** * Requests the logic channel number (LCN) of the current channel. */ + @CallSuper public void requestCurrentChannelLcn() { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -799,6 +808,7 @@ public abstract class TvInteractiveAppService extends Service { /** * Requests stream volume. */ + @CallSuper public void requestStreamVolume() { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -821,6 +831,7 @@ public abstract class TvInteractiveAppService extends Service { /** * Requests the list of {@link TvTrackInfo}. */ + @CallSuper public void requestTrackInfoList() { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -845,6 +856,7 @@ public abstract class TvInteractiveAppService extends Service { * * @see android.media.tv.TvInputInfo */ + @CallSuper public void requestCurrentTvInputId() { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -869,6 +881,7 @@ public abstract class TvInteractiveAppService extends Service { * * @param request The advertisement request */ + @CallSuper public void requestAd(@NonNull final AdRequest request) { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @@ -1032,6 +1045,7 @@ public abstract class TvInteractiveAppService extends Service { * used when the state is not * {@link TvInteractiveAppManager#INTERACTIVE_APP_STATE_ERROR}. */ + @CallSuper public void notifySessionStateChanged( @TvInteractiveAppManager.InteractiveAppState int state, @TvInteractiveAppManager.ErrorCode int err) { @@ -1062,6 +1076,7 @@ public abstract class TvInteractiveAppService extends Service { * * @see #onCreateBiInteractiveApp(Uri, Bundle) */ + @CallSuper public final void notifyBiInteractiveAppCreated( @NonNull Uri biIAppUri, @Nullable String biIAppId) { executeOrPostRunnableOnMainThread(new Runnable() { @@ -1087,6 +1102,7 @@ public abstract class TvInteractiveAppService extends Service { * Notifies when the digital teletext app state is changed. * @param state the current state. */ + @CallSuper public final void notifyTeletextAppStateChanged( @TvInteractiveAppManager.TeletextAppState int state) { executeOrPostRunnableOnMainThread(new Runnable() { 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/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml index 3fb3fd475ab3..5c90fd019cd8 100644 --- a/packages/BackupRestoreConfirmation/res/values/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values/strings.xml @@ -44,8 +44,6 @@ <string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string> <!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. --> <string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string> - <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. --> - <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string> <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. --> <string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string> diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java index d6b6bf8d1e56..3c790f0e24ee 100644 --- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java +++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java @@ -27,8 +27,6 @@ import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.storage.IStorageManager; -import android.os.storage.StorageManager; import android.text.Editable; import android.text.TextWatcher; import android.util.Slog; @@ -66,10 +64,8 @@ public class BackupRestoreConfirmation extends Activity { Handler mHandler; IBackupManager mBackupManager; - IStorageManager mStorageManager; FullObserver mObserver; int mToken; - boolean mIsEncrypted; boolean mDidAcknowledge; String mAction; @@ -144,7 +140,6 @@ public class BackupRestoreConfirmation extends Activity { } mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE)); - mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount")); mHandler = new ObserverHandler(getApplicationContext()); final Object oldObserver = getLastNonConfigurationInstance(); @@ -248,20 +243,13 @@ public class BackupRestoreConfirmation extends Activity { mDenyButton.setEnabled(!mDidAcknowledge); } - // We vary the password prompt depending on whether one is predefined, and whether - // the device is encrypted. - mIsEncrypted = deviceIsEncrypted(); + // We vary the password prompt depending on whether one is predefined. if (!haveBackupPassword()) { curPwDesc.setVisibility(View.GONE); mCurPassword.setVisibility(View.GONE); if (layoutId == R.layout.confirm_backup) { TextView encPwDesc = findViewById(R.id.enc_password_desc); - if (mIsEncrypted) { - encPwDesc.setText(R.string.backup_enc_password_required); - monitorEncryptionPassword(); - } else { - encPwDesc.setText(R.string.backup_enc_password_optional); - } + encPwDesc.setText(R.string.backup_enc_password_optional); } } } @@ -312,20 +300,6 @@ public class BackupRestoreConfirmation extends Activity { } } - boolean deviceIsEncrypted() { - try { - return mStorageManager.getEncryptionState() - != StorageManager.ENCRYPTION_STATE_NONE - && mStorageManager.getPasswordType() - != StorageManager.CRYPT_TYPE_DEFAULT; - } catch (Exception e) { - // If we can't talk to the storagemanager service we have a serious problem; fail - // "secure" i.e. assuming that the device is encrypted. - Slog.e(TAG, "Unable to communicate with storagemanager service: " + e.getMessage()); - return true; - } - } - boolean haveBackupPassword() { try { return mBackupManager.hasBackupPassword(); diff --git a/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml b/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml index 125fee6282d5..ece7bbafc654 100644 --- a/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml +++ b/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml @@ -20,6 +20,6 @@ <corners android:topLeftRadius="16dp" android:topRightRadius="16dp" android:bottomLeftRadius="16dp" android:bottomRightRadius="16dp"/> <stroke - android:width="2dp" + android:width="1dp" android:color="@android:color/system_accent1_600" /> </shape>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml b/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml new file mode 100644 index 000000000000..f8515c33d57f --- /dev/null +++ b/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml @@ -0,0 +1,23 @@ +<!-- + ~ 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. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path android:fillColor="@android:color/white" + android:pathData="M7,20H4Q3.175,20 2.588,19.413Q2,18.825 2,18V6Q2,5.175 2.588,4.588Q3.175,4 4,4H20V6H4Q4,6 4,6Q4,6 4,6V18Q4,18 4,18Q4,18 4,18H7ZM9,20V18.2Q8.55,17.775 8.275,17.225Q8,16.675 8,16Q8,15.325 8.275,14.775Q8.55,14.225 9,13.8V12H13V13.8Q13.45,14.225 13.725,14.775Q14,15.325 14,16Q14,16.675 13.725,17.225Q13.45,17.775 13,18.2V20ZM11,17.5Q11.65,17.5 12.075,17.075Q12.5,16.65 12.5,16Q12.5,15.35 12.075,14.925Q11.65,14.5 11,14.5Q10.35,14.5 9.925,14.925Q9.5,15.35 9.5,16Q9.5,16.65 9.925,17.075Q10.35,17.5 11,17.5ZM21,20H16Q15.575,20 15.288,19.712Q15,19.425 15,19V10Q15,9.575 15.288,9.287Q15.575,9 16,9H21Q21.425,9 21.712,9.287Q22,9.575 22,10V19Q22,19.425 21.712,19.712Q21.425,20 21,20ZM17,18H20V11H17Z"/> +</vector>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/drawable/ic_watch.xml b/packages/CompanionDeviceManager/res/drawable/ic_watch.xml new file mode 100644 index 000000000000..44a40b9fede3 --- /dev/null +++ b/packages/CompanionDeviceManager/res/drawable/ic_watch.xml @@ -0,0 +1,25 @@ +<!-- + ~ 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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path android:fillColor="@android:color/white" + android:pathData="M9,22 L7.65,17.45Q6.45,16.5 5.725,15.075Q5,13.65 5,12Q5,10.35 5.725,8.925Q6.45,7.5 7.65,6.55L9,2H15L16.35,6.55Q17.55,7.5 18.275,8.925Q19,10.35 19,12Q19,13.65 18.275,15.075Q17.55,16.5 16.35,17.45L15,22ZM12,17Q14.075,17 15.538,15.537Q17,14.075 17,12Q17,9.925 15.538,8.462Q14.075,7 12,7Q9.925,7 8.463,8.462Q7,9.925 7,12Q7,14.075 8.463,15.537Q9.925,17 12,17ZM10.1,5.25Q11.075,4.975 12,4.975Q12.925,4.975 13.9,5.25L13.5,4H10.5ZM10.5,20H13.5L13.9,18.75Q12.925,19.025 12,19.025Q11.075,19.025 10.1,18.75ZM10.1,4H10.5H13.5H13.9Q12.925,4 12,4Q11.075,4 10.1,4ZM10.5,20H10.1Q11.075,20 12,20Q12.925,20 13.9,20H13.5Z"/> +</vector>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml index 9e5b1663ff45..8eec33aeb4ee 100644 --- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml +++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml @@ -20,6 +20,15 @@ <!-- A header for selfManaged devices only. --> <include layout="@layout/vendor_header" /> + <ImageView + android:id="@+id/profile_icon" + android:layout_width="match_parent" + android:layout_height="32dp" + android:gravity="center" + android:layout_marginBottom="12dp" + android:layout_marginTop="1dp" + android:tint="@android:color/system_accent1_600"/> + <!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. --> <TextView @@ -28,7 +37,8 @@ android:layout_height="wrap_content" android:gravity="center" android:paddingHorizontal="12dp" - style="@*android:style/TextAppearance.Widget.Toolbar.Title"/> + android:layout_marginBottom="12dp" + style="@*android:style/TextAppearance.Widget.Toolbar.Title" /> <TextView android:id="@+id/summary" @@ -45,11 +55,29 @@ android:layout_height="0dp" android:layout_weight="1"> - <androidx.recyclerview.widget.RecyclerView - android:id="@+id/device_list" + <LinearLayout + android:id="@+id/multiple_device_list" android:layout_width="match_parent" - android:scrollbars="vertical" - android:layout_height="200dp" /> + android:layout_height="wrap_content" + android:orientation="vertical" + android:visibility="gone"> + + <View + android:id="@+id/border_top" + android:layout_marginTop="12dp" + style="@style/DeviceListBorder" /> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/device_list" + android:layout_width="match_parent" + android:scrollbars="vertical" + android:layout_height="200dp" /> + + <View + android:id="@+id/border_bottom" + style="@style/DeviceListBorder" /> + + </LinearLayout> <androidx.recyclerview.widget.RecyclerView android:id="@+id/permission_list" diff --git a/packages/CompanionDeviceManager/res/layout/list_item_device.xml b/packages/CompanionDeviceManager/res/layout/list_item_device.xml index b732b1bd9ad8..3c8a81f4fe83 100644 --- a/packages/CompanionDeviceManager/res/layout/list_item_device.xml +++ b/packages/CompanionDeviceManager/res/layout/list_item_device.xml @@ -28,7 +28,8 @@ android:id="@android:id/icon" android:layout_width="24dp" android:layout_height="24dp" - android:layout_marginRight="12dp"/> + android:layout_marginRight="12dp" + android:tint="@android:color/system_accent1_600"/> <TextView android:id="@android:id/text1" diff --git a/packages/CompanionDeviceManager/res/layout/list_item_permission.xml b/packages/CompanionDeviceManager/res/layout/list_item_permission.xml index b8a0f7938f0b..79aa4e7e8927 100644 --- a/packages/CompanionDeviceManager/res/layout/list_item_permission.xml +++ b/packages/CompanionDeviceManager/res/layout/list_item_permission.xml @@ -27,6 +27,7 @@ android:layout_height="24dp" android:layout_marginTop="7dp" android:layout_marginEnd="12dp" + android:tint="@android:color/system_accent1_600" android:contentDescription="Permission Icon"/> <LinearLayout diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml index 55a199813388..67fc6c2dc864 100644 --- a/packages/CompanionDeviceManager/res/values/strings.xml +++ b/packages/CompanionDeviceManager/res/values/strings.xml @@ -82,7 +82,7 @@ <string name="permission_notification">Notifications</string> <!-- Description of notification permission of COMPUTER profile [CHAR LIMIT=NONE] --> - <string name="permission_notification_summary">Can read all notifications, including information like contracts, messages, and photos</string> + <string name="permission_notification_summary">Can read all notifications, including information like contacts, messages, and photos</string> <!-- Storage permission will be granted of COMPUTER profile [CHAR LIMIT=30] --> <string name="permission_storage">Photos and media</string> diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml index 4a267db3ceec..6eaffd4c3cfe 100644 --- a/packages/CompanionDeviceManager/res/values/styles.xml +++ b/packages/CompanionDeviceManager/res/values/styles.xml @@ -65,4 +65,10 @@ <item name="android:background">@drawable/btn_negative_multiple_devices</item> </style> + <style name="DeviceListBorder"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">1dp</item> + <item name="android:background">@android:color/system_accent1_300</item> + </style> + </resources>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java index 0ab126a7dae0..f752b697c4a5 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java @@ -29,6 +29,7 @@ import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_NOTI import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_STORAGE; import static com.android.companiondevicemanager.Utils.getApplicationLabel; import static com.android.companiondevicemanager.Utils.getHtmlFromResources; +import static com.android.companiondevicemanager.Utils.getIcon; import static com.android.companiondevicemanager.Utils.getVendorHeaderIcon; import static com.android.companiondevicemanager.Utils.getVendorHeaderName; import static com.android.companiondevicemanager.Utils.prepareResultReceiverForIpc; @@ -106,6 +107,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements private TextView mTitle; private TextView mSummary; + // Present for single device and multiple device only. + private ImageView mProfileIcon; + // Only present for selfManaged devices. private ImageView mVendorHeaderImage; private TextView mVendorHeaderName; @@ -119,10 +123,11 @@ public class CompanionDeviceActivity extends FragmentActivity implements // regular. private Button mButtonAllow; private Button mButtonNotAllow; - // Present for multiple devices association requests only. + // Present for multiple device association requests only. private Button mButtonNotAllowMultipleDevices; private LinearLayout mAssociationConfirmationDialog; + private LinearLayout mMultipleDeviceList; private RelativeLayout mVendorHeader; // The recycler view is only shown for multiple-device regular association request, after @@ -130,6 +135,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements private @Nullable RecyclerView mDeviceListRecyclerView; private @Nullable DeviceListAdapter mDeviceAdapter; + // The recycler view is only shown for selfManaged association request. private @Nullable RecyclerView mPermissionListRecyclerView; private @Nullable PermissionListAdapter mPermissionListAdapter; @@ -243,12 +249,15 @@ public class CompanionDeviceActivity extends FragmentActivity implements setContentView(R.layout.activity_confirmation); + mMultipleDeviceList = findViewById(R.id.multiple_device_list); mAssociationConfirmationDialog = findViewById(R.id.activity_confirmation); mVendorHeader = findViewById(R.id.vendor_header); mTitle = findViewById(R.id.title); mSummary = findViewById(R.id.summary); + mProfileIcon = findViewById(R.id.profile_icon); + mVendorHeaderImage = findViewById(R.id.vendor_header_image); mVendorHeaderName = findViewById(R.id.vendor_header_name); mVendorHeaderButton = findViewById(R.id.vendor_header_button); @@ -420,6 +429,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mVendorHeaderName.setText(vendorName); mDeviceListRecyclerView.setVisibility(View.GONE); + mProfileIcon.setVisibility(View.GONE); mVendorHeader.setVisibility(View.VISIBLE); } @@ -447,17 +457,22 @@ public class CompanionDeviceActivity extends FragmentActivity implements final Spanned title = getHtmlFromResources( this, R.string.confirmation_title, appLabel, deviceName); final Spanned summary; + final Drawable profileIcon; if (deviceProfile == null) { summary = getHtmlFromResources(this, R.string.summary_generic); + profileIcon = getIcon(this, R.drawable.ic_device_other); + mSummary.setVisibility(View.GONE); } else if (deviceProfile.equals(DEVICE_PROFILE_WATCH)) { summary = getHtmlFromResources(this, R.string.summary_watch, appLabel, deviceName); + profileIcon = getIcon(this, R.drawable.ic_watch); } else { throw new RuntimeException("Unsupported profile " + deviceProfile); } mTitle.setText(title); mSummary.setText(summary); + mProfileIcon.setImageDrawable(profileIcon); } private void initUiForMultipleDevices(CharSequence appLabel) { @@ -467,12 +482,16 @@ public class CompanionDeviceActivity extends FragmentActivity implements final String profileName; final Spanned summary; + final Drawable profileIcon; if (deviceProfile == null) { profileName = getString(R.string.profile_name_generic); summary = getHtmlFromResources(this, R.string.summary_generic); + profileIcon = getIcon(this, R.drawable.ic_device_other); + mSummary.setVisibility(View.GONE); } else if (deviceProfile.equals(DEVICE_PROFILE_WATCH)) { profileName = getString(R.string.profile_name_watch); summary = getHtmlFromResources(this, R.string.summary_watch, appLabel); + profileIcon = getIcon(this, R.drawable.ic_watch); } else { throw new RuntimeException("Unsupported profile " + deviceProfile); } @@ -481,6 +500,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mTitle.setText(title); mSummary.setText(summary); + mProfileIcon.setImageDrawable(profileIcon); mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick); @@ -496,6 +516,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mButtonAllow.setVisibility(View.GONE); mButtonNotAllow.setVisibility(View.GONE); mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE); + mMultipleDeviceList.setVisibility(View.VISIBLE); } private void onListItemClick(int position) { diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/Utils.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/Utils.java index d5b2f0a748f1..1852e82cb9f9 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/Utils.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/Utils.java @@ -22,7 +22,6 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.ApplicationInfoFlags; -import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; @@ -124,7 +123,6 @@ class Utils { static @NonNull Drawable getIcon(@NonNull Context context, int resId) { Drawable icon = context.getResources().getDrawable(resId, null); - icon.setTint(Color.DKGRAY); return icon; } diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp index 66527802a0e4..217a1f67c336 100644 --- a/packages/ConnectivityT/framework-t/Android.bp +++ b/packages/ConnectivityT/framework-t/Android.bp @@ -154,17 +154,17 @@ filegroup { ], } +// TODO: remove this empty filegroup. filegroup { name: "framework-connectivity-tiramisu-sources", - srcs: [ - ":framework-connectivity-ethernet-sources", - ], + srcs: [], visibility: ["//frameworks/base"], } filegroup { name: "framework-connectivity-tiramisu-updatable-sources", srcs: [ + ":framework-connectivity-ethernet-sources", ":framework-connectivity-ipsec-sources", ":framework-connectivity-netstats-sources", ":framework-connectivity-nsd-sources", diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java index 9bffbfb27a8d..61b34d0bcfe6 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java +++ b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java @@ -34,8 +34,9 @@ public final class ConnectivityFrameworkInitializerTiramisu { private ConnectivityFrameworkInitializerTiramisu() {} /** - * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to - * {@link Context}, so that {@link Context#getSystemService} can return them. + * Called by {@link SystemServiceRegistry}'s static initializer and registers NetworkStats, nsd, + * ipsec and ethernet services to {@link Context}, so that {@link Context#getSystemService} can + * return them. * * @throws IllegalStateException if this is called anywhere besides * {@link SystemServiceRegistry}. @@ -68,5 +69,14 @@ public final class ConnectivityFrameworkInitializerTiramisu { return new NetworkStatsManager(context, service); } ); + + SystemServiceRegistry.registerContextAwareService( + Context.ETHERNET_SERVICE, + EthernetManager.class, + (context, serviceBinder) -> { + IEthernetManager service = IEthernetManager.Stub.asInterface(serviceBinder); + return new EthernetManager(context, service); + } + ); } } diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java index 72243f9e87d9..793f28d5aa59 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java @@ -33,7 +33,7 @@ import android.os.Build; import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; -import com.android.internal.os.BackgroundThread; +import com.android.modules.utils.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -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/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java index f681ba1c3853..06f2a621bcae 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java @@ -327,16 +327,11 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is * for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only * counting iface stats. - * @param set usage state of this {@link Entry}. Should be one of the following - * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}. + * @param set usage state of this {@link Entry}. * @param tag tag of this {@link Entry}. - * @param metered metered state of this {@link Entry}. Should be one of the following - * values: {link #METERED_YES}, {link #METERED_NO}. - * @param roaming roaming state of this {@link Entry}. Should be one of the following - * values: {link #ROAMING_YES}, {link #ROAMING_NO}. - * @param defaultNetwork default network status of this {@link Entry}. Should be one - * of the following values: {link #DEFAULT_NETWORK_YES}, - * {link #DEFAULT_NETWORK_NO}. + * @param metered metered state of this {@link Entry}. + * @param roaming roaming state of this {@link Entry}. + * @param defaultNetwork default network status of this {@link Entry}. * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should * represent the contents of IP packets, including IP headers. * @param rxPackets Number of packets received for this {@link Entry}. Statistics should @@ -401,8 +396,7 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent } /** - * @return the set state of this entry. Should be one of the following - * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}. + * @return the set state of this entry. */ @State public int getSet() { return set; @@ -416,24 +410,21 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent } /** - * @return the metered state. Should be one of the following - * values: {link #METERED_YES}, {link #METERED_NO}. + * @return the metered state. */ @Meteredness public int getMetered() { return metered; } /** - * @return the roaming state. Should be one of the following - * values: {link #ROAMING_YES}, {link #ROAMING_NO}. + * @return the roaming state. */ @Roaming public int getRoaming() { return roaming; } /** - * @return the default network state. Should be one of the following - * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}. + * @return the default network state. */ @DefaultNetwork public int getDefaultNetwork() { return defaultNetwork; diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java index 735c44d5c87e..e385b33447f0 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java @@ -36,6 +36,7 @@ import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRation import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.net.NetworkStats.State; import android.net.NetworkStatsHistory.Entry; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; @@ -102,7 +103,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private ArrayMap<Key, NetworkStatsHistory> mStats = new ArrayMap<>(); - private final long mBucketDuration; + private final long mBucketDurationMillis; private long mStartMillis; private long mEndMillis; @@ -115,8 +116,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param bucketDuration duration of the buckets in this object, in milliseconds. * @hide */ - public NetworkStatsCollection(long bucketDuration) { - mBucketDuration = bucketDuration; + public NetworkStatsCollection(long bucketDurationMillis) { + mBucketDurationMillis = bucketDurationMillis; reset(); } @@ -148,7 +149,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W if (mStartMillis == Long.MAX_VALUE) { return Long.MAX_VALUE; } else { - return mStartMillis + mBucketDuration; + return mStartMillis + mBucketDurationMillis; } } @@ -184,10 +185,10 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W || time == SubscriptionPlan.TIME_UNKNOWN) { return time; } else { - final long mod = time % mBucketDuration; + final long mod = time % mBucketDurationMillis; if (mod > 0) { time -= mod; - time += mBucketDuration; + time += mBucketDurationMillis; } return time; } @@ -200,7 +201,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W || time == SubscriptionPlan.TIME_UNKNOWN) { return time; } else { - final long mod = time % mBucketDuration; + final long mod = time % mBucketDurationMillis; if (mod > 0) { time -= mod; } @@ -247,10 +248,10 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // 180 days of history should be enough for anyone; if we end up needing // more, we'll dynamically grow the history object. final int bucketEstimate = (int) NetworkStatsUtils.constrain( - ((end - start) / mBucketDuration), 0, - (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration); + ((end - start) / mBucketDurationMillis), 0, + (180 * DateUtils.DAY_IN_MILLIS) / mBucketDurationMillis); final NetworkStatsHistory combined = new NetworkStatsHistory( - mBucketDuration, bucketEstimate, fields); + mBucketDurationMillis, bucketEstimate, fields); // shortcut when we know stats will be empty if (start == end) return combined; @@ -343,7 +344,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // Finally we can slice data as originally requested final NetworkStatsHistory sliced = new NetworkStatsHistory( - mBucketDuration, bucketEstimate, fields); + mBucketDurationMillis, bucketEstimate, fields); sliced.recordHistory(combined, start, end); return sliced; } else { @@ -458,9 +459,9 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // update when no existing, or when bucket duration changed NetworkStatsHistory updated = null; if (existing == null) { - updated = new NetworkStatsHistory(mBucketDuration, 10); - } else if (existing.getBucketDuration() != mBucketDuration) { - updated = new NetworkStatsHistory(existing, mBucketDuration); + updated = new NetworkStatsHistory(mBucketDurationMillis, 10); + } else if (existing.getBucketDuration() != mBucketDurationMillis) { + updated = new NetworkStatsHistory(existing, mBucketDurationMillis); } if (updated != null) { @@ -702,7 +703,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private int estimateBuckets() { return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5) - / mBucketDuration); + / mBucketDurationMillis); } private ArrayList<Key> getSortedKeys() { @@ -828,7 +829,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * Builder class for {@link NetworkStatsCollection}. */ public static final class Builder { - private final long mBucketDuration; + private final long mBucketDurationMillis; private final ArrayMap<Key, NetworkStatsHistory> mEntries = new ArrayMap<>(); /** @@ -836,8 +837,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * * @param bucketDuration Duration of the buckets of the object, in milliseconds. */ - public Builder(long bucketDuration) { - mBucketDuration = bucketDuration; + public Builder(long bucketDurationMillis) { + mBucketDurationMillis = bucketDurationMillis; } /** @@ -855,7 +856,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W final List<Entry> historyEntries = history.getEntries(); final NetworkStatsHistory.Builder historyBuilder = - new NetworkStatsHistory.Builder(mBucketDuration, historyEntries.size()); + new NetworkStatsHistory.Builder(mBucketDurationMillis, historyEntries.size()); for (Entry entry : historyEntries) { historyBuilder.addEntry(entry); } @@ -871,7 +872,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W */ @NonNull public NetworkStatsCollection build() { - final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); + final NetworkStatsCollection collection = + new NetworkStatsCollection(mBucketDurationMillis); for (int i = 0; i < mEntries.size(); i++) { collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i)); } @@ -883,7 +885,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * the identifier that associate with the {@link NetworkStatsHistory} object to identify * a certain record in the {@link NetworkStatsCollection} object. */ - public static class Key { + public static final class Key { /** @hide */ public final NetworkIdentitySet ident; /** @hide */ @@ -903,7 +905,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param set Set of the record, see {@code NetworkStats#SET_*}. * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}. */ - public Key(@NonNull Set<NetworkIdentity> ident, int uid, int set, int tag) { + public Key(@NonNull Set<NetworkIdentity> ident, int uid, @State int set, int tag) { this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag); } diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp index 5100e7c5b9a4..4b799c599be9 100644 --- a/packages/ConnectivityT/service/Android.bp +++ b/packages/ConnectivityT/service/Android.bp @@ -102,17 +102,16 @@ filegroup { ], path: "src", visibility: [ - "//frameworks/opt/net/ethernet", + "//frameworks/opt/net/ethernet/tests", ], } // Connectivity-T common libraries. +// TODO: remove this empty filegroup. filegroup { name: "services.connectivity-tiramisu-sources", - srcs: [ - ":services.connectivity-ethernet-sources", - ], + srcs: [], path: "src", visibility: ["//frameworks/base/services/core"], } @@ -120,6 +119,7 @@ filegroup { filegroup { name: "services.connectivity-tiramisu-updatable-sources", srcs: [ + ":services.connectivity-ethernet-sources", ":services.connectivity-ipsec-sources", ":services.connectivity-netstats-sources", ":services.connectivity-nsd-sources", diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java index 2f771260ac1b..ad0be5862c5d 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java @@ -48,10 +48,16 @@ import java.util.Arrays; */ @RunWith(AndroidJUnit4.class) public class IpConfigStoreTest { + private static final int KEY_CONFIG = 17; + private static final String IFACE_1 = "eth0"; + private static final String IFACE_2 = "eth1"; + private static final String IP_ADDR_1 = "192.168.1.10/24"; + private static final String IP_ADDR_2 = "192.168.1.20/24"; + private static final String DNS_IP_ADDR_1 = "1.2.3.4"; + private static final String DNS_IP_ADDR_2 = "5.6.7.8"; @Test public void backwardCompatibility2to3() throws IOException { - final int KEY_CONFIG = 17; ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream outputStream = new DataOutputStream(byteStream); @@ -73,13 +79,6 @@ public class IpConfigStoreTest { @Test public void staticIpMultiNetworks() throws Exception { - final String IFACE_1 = "eth0"; - final String IFACE_2 = "eth1"; - final String IP_ADDR_1 = "192.168.1.10/24"; - final String IP_ADDR_2 = "192.168.1.20/24"; - final String DNS_IP_ADDR_1 = "1.2.3.4"; - final String DNS_IP_ADDR_2 = "5.6.7.8"; - final ArrayList<InetAddress> dnsServers = new ArrayList<>(); dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); @@ -144,11 +143,11 @@ public class IpConfigStoreTest { /** Synchronously writes into given byte steam */ private static class MockedDelayedDiskWrite extends DelayedDiskWrite { - final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream(); @Override public void write(String filePath, Writer w) { - DataOutputStream outputStream = new DataOutputStream(byteStream); + DataOutputStream outputStream = new DataOutputStream(mByteStream); try { w.onWriteCalled(outputStream); diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 042fef23cbe6..579e3d7a6d39 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1293,6 +1293,8 @@ <string name="cancel">Cancel</string> <!-- Button label for generic OK action [CHAR LIMIT=20] --> <string name="okay">OK</string> + <!-- Button label for generic Done action, to be pressed when an action has been completed [CHAR LIMIT=20] --> + <string name="done">Done</string> <!-- Label for the settings activity for controlling apps that can schedule alarms [CHAR LIMIT=30] --> <string name="alarms_and_reminders_label">Alarms and reminders</string> @@ -1342,7 +1344,9 @@ <string name="notice_header" translatable="false"></string> <!-- Name of the phone device. [CHAR LIMIT=30] --> - <string name="media_transfer_this_device_name">This phone</string> + <string name="media_transfer_this_device_name" product="default">This phone</string> + <!-- Name of the tablet device. [CHAR LIMIT=30] --> + <string name="media_transfer_this_device_name" product="tablet">This tablet</string> <!-- Name of the phone device with an active remote session. [CHAR LIMIT=30] --> <string name="media_transfer_this_phone">This phone</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java index 17db45dcaeb3..e4efae2f1a36 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -23,7 +23,6 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.res.TypedArray; -import android.os.Build; import android.os.UserHandle; import android.text.TextUtils; import android.util.AttributeSet; @@ -33,8 +32,6 @@ import android.widget.TextView; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; -import com.android.internal.util.Preconditions; - /** * Helper class for managing settings preferences that can be disabled * by device admins via user restrictions. @@ -42,8 +39,8 @@ import com.android.internal.util.Preconditions; public class RestrictedPreferenceHelper { private final Context mContext; private final Preference mPreference; - final String packageName; - final int uid; + String packageName; + int uid; private boolean mDisabledByAdmin; private EnforcedAdmin mEnforcedAdmin; @@ -219,6 +216,11 @@ public class RestrictedPreferenceHelper { return mDisabledByAppOps; } + public void updatePackageDetails(String packageName, int uid) { + this.packageName = packageName; + this.uid = uid; + } + private void updateDisabledState() { if (!(mPreference instanceof RestrictedTopLevelPreference)) { mPreference.setEnabled(!(mDisabledByAdmin || mDisabledByAppOps)); diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java index c607d742938a..091e3228d437 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java @@ -18,8 +18,11 @@ package com.android.settingslib; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import android.annotation.NonNull; +import android.app.AppOpsManager; import android.content.Context; import android.content.res.TypedArray; +import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; import android.util.TypedValue; @@ -28,6 +31,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.VisibleForTesting; import androidx.core.content.res.TypedArrayUtils; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceViewHolder; @@ -39,6 +43,7 @@ import androidx.preference.SwitchPreference; */ public class RestrictedSwitchPreference extends SwitchPreference { RestrictedPreferenceHelper mHelper; + AppOpsManager mAppOpsManager; boolean mUseAdditionalSummary = false; CharSequence mRestrictedSwitchSummary; private int mIconSize; @@ -90,6 +95,11 @@ public class RestrictedSwitchPreference extends SwitchPreference { this(context, null); } + @VisibleForTesting + public void setAppOps(AppOpsManager appOps) { + mAppOpsManager = appOps; + } + public void setIconSize(int iconSize) { mIconSize = iconSize; } @@ -97,6 +107,12 @@ public class RestrictedSwitchPreference extends SwitchPreference { @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); + final View switchView = holder.findViewById(android.R.id.switch_widget); + if (switchView != null) { + final View rootView = switchView.getRootView(); + rootView.setFilterTouchesWhenObscured(true); + } + mHelper.onBindViewHolder(holder); CharSequence switchSummary; @@ -164,11 +180,18 @@ public class RestrictedSwitchPreference extends SwitchPreference { @Override public void setEnabled(boolean enabled) { + boolean changed = false; if (enabled && isDisabledByAdmin()) { mHelper.setDisabledByAdmin(null); - return; + changed = true; + } + if (enabled && isDisabledByAppOps()) { + mHelper.setDisabledByAppOps(false); + changed = true; + } + if (!changed) { + super.setEnabled(enabled); } - super.setEnabled(enabled); } public void setDisabledByAdmin(EnforcedAdmin admin) { @@ -180,4 +203,38 @@ public class RestrictedSwitchPreference extends SwitchPreference { public boolean isDisabledByAdmin() { return mHelper.isDisabledByAdmin(); } + + private void setDisabledByAppOps(boolean disabled) { + if (mHelper.setDisabledByAppOps(disabled)) { + notifyChanged(); + } + } + + public boolean isDisabledByAppOps() { + return mHelper.isDisabledByAppOps(); + } + + public int getUid() { + return mHelper != null ? mHelper.uid : Process.INVALID_UID; + } + + public String getPackageName() { + return mHelper != null ? mHelper.packageName : null; + } + + public void updateState(@NonNull String packageName, int uid, boolean isEnabled) { + mHelper.updatePackageDetails(packageName, uid); + if (mAppOpsManager == null) { + mAppOpsManager = getContext().getSystemService(AppOpsManager.class); + } + final int mode = mAppOpsManager.noteOpNoThrow( + AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, + uid, packageName); + final boolean appOpsAllowed = mode == AppOpsManager.MODE_ALLOWED; + if (appOpsAllowed || isEnabled) { + setEnabled(true); + } else { + setDisabledByAppOps(true); + } + } } 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/users/AvatarPickerActivity.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java index 75bb70a123c3..8a1e91b4dcd8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java @@ -106,13 +106,13 @@ public class AvatarPickerActivity extends Activity { FooterButton secondaryButton = new FooterButton.Builder(this) - .setText("Cancel") + .setText(getString(android.R.string.cancel)) .setListener(view -> cancel()) .build(); mDoneButton = new FooterButton.Builder(this) - .setText("Done") + .setText(getString(R.string.done)) .setListener(view -> mAdapter.returnSelectionResult()) .build(); mDoneButton.setEnabled(false); 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/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index dae63a8b0e3c..e93371d3690c 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -536,10 +536,11 @@ <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" /> <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" /> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" /> + <uses-permission android:name="android.permission.MANAGE_WIFI_INTERFACES" /> <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" /> <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover - P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. --> - <uses-permission android:name="android.permission.MANAGE_WIFI_AUTO_JOIN" /> + P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. --> + <uses-permission android:name="android.permission.MANAGE_WIFI_NETWORK_SELECTION" /> <!-- Permission required for CTS tests to enable/disable rate limiting toasts. --> <uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" /> @@ -668,6 +669,9 @@ <!-- Permission required for CTS test - CtsTelephonyTestCases --> <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" /> + <!-- Permission required for CTS test - CtsAppEnumerationTestCases --> + <uses-permission android:name="android.permission.MAKE_UID_VISIBLE" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index e24b2d6c6aa9..4b45cc338a6a 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -314,6 +314,11 @@ <!-- To change system captions state --> <uses-permission android:name="android.permission.SET_SYSTEM_AUDIO_CAPTION" /> + <!-- Compat framework --> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" /> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> + <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> 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/clipboard_edit_text_activity.xml b/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml index 8f6753a095d0..da4088f6731d 100644 --- a/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml +++ b/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml @@ -36,6 +36,7 @@ android:tooltipText="@*android:string/share" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/copy_button" + android:tint="?android:attr/textColorPrimary" android:src="@drawable/ic_screenshot_share" /> <ScrollView diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml index 91d81a2b0b2f..cb63300f819b 100644 --- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml +++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml @@ -19,6 +19,7 @@ android:id="@+id/date_view" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding" android:gravity="center_horizontal" android:textColor="@android:color/white" android:shadowColor="@color/keyguard_shadow_color" diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml index 3900ea56dda3..76fe58c29852 100644 --- a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml +++ b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml @@ -19,6 +19,7 @@ android:id="@+id/weather_view" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding" android:textColor="@android:color/white" android:shadowColor="@color/keyguard_shadow_color" android:shadowRadius="?attr/shadowRadius" diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml index 806804f2fc47..eeb37c7b062d 100644 --- a/packages/SystemUI/res/layout/media_output_list_item.xml +++ b/packages/SystemUI/res/layout/media_output_list_item.xml @@ -62,20 +62,22 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical|start" android:layout_marginStart="56dp" + android:layout_marginEnd="56dp" android:ellipsize="end" android:maxLines="1" android:fontFamily="@*android:string/config_headlineFontFamilyMedium" android:textSize="16sp"/> - <RelativeLayout + <LinearLayout android:id="@+id/two_line_layout" + android:orientation="vertical" android:layout_width="wrap_content" android:layout_gravity="center_vertical|start" android:layout_height="48dp" + android:layout_marginEnd="56dp" android:layout_marginStart="56dp"> <TextView android:id="@+id/two_line_title" - android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" @@ -85,18 +87,15 @@ android:textSize="16sp"/> <TextView android:id="@+id/subtitle" - android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:layout_alignParentBottom="true" android:ellipsize="end" android:maxLines="1" android:textColor="@color/media_dialog_inactive_item_main_content" android:textSize="14sp" android:fontFamily="@*android:string/config_bodyFontFamily" android:visibility="gone"/> - </RelativeLayout> + </LinearLayout> <ProgressBar android:id="@+id/volume_indeterminate_progress" diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml index 812277634d09..ad2bc79a5c96 100644 --- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml +++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml @@ -22,7 +22,10 @@ android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="center_vertical|end" - android:focusable="true" > + android:focusable="true" + android:clipChildren="false" + android:clipToPadding="false" + > <LinearLayout android:id="@+id/icons_container" @@ -34,5 +37,7 @@ android:layout_gravity="center" android:minWidth="@dimen/ongoing_appops_chip_min_width" android:maxWidth="@dimen/ongoing_appops_chip_max_width" + android:clipChildren="false" + android:clipToPadding="false" /> </com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/system_event_animation_window.xml b/packages/SystemUI/res/layout/system_event_animation_window.xml index c92dec9dd643..e6868b34df02 100644 --- a/packages/SystemUI/res/layout/system_event_animation_window.xml +++ b/packages/SystemUI/res/layout/system_event_animation_window.xml @@ -19,17 +19,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical|end" - android:paddingTop="@dimen/status_bar_padding_top" - android:paddingEnd="8dp" + android:clipChildren="false" + android:clipToPadding="false" > - - <ImageView - android:id="@+id/dot_view" - android:layout_width="10dp" - android:layout_height="10dp" - android:layout_gravity="center_vertical|end" - android:src="@drawable/system_animation_ongoing_dot" - android:visibility="invisible" - /> - </FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml index f3d83645a8e0..89191984b9e8 100644 --- a/packages/SystemUI/res/values-land/styles.xml +++ b/packages/SystemUI/res/values-land/styles.xml @@ -18,15 +18,4 @@ <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer"> <item name="android:layout_width">360dp</item> </style> - - <style name="DockedDividerBackground"> - <item name="android:layout_width">10dp</item> - <item name="android:layout_height">match_parent</item> - <item name="android:layout_gravity">center_horizontal</item> - </style> - - <style name="DockedDividerMinimizedShadow"> - <item name="android:layout_width">8dp</item> - <item name="android:layout_height">match_parent</item> - </style> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 512f9160162c..ffae6015c732 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1367,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> @@ -1379,6 +1376,7 @@ <dimen name="dream_overlay_complication_weather_text_size">18sp</dimen> <dimen name="dream_overlay_complication_preview_text_size">36sp</dimen> <dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen> + <dimen name="dream_overlay_complication_shadow_padding">2dp</dimen> <!-- The position of the end guide, which dream overlay complications can align their start with if their end is aligned with the parent end. Represented as the percentage over from the diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 9f2f1c1978c6..d230f33f4939 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1193,10 +1193,7 @@ <string name="wallet_lockscreen_settings_label">Lock screen settings</string> <!-- QR Code Scanner label, title [CHAR LIMIT=32] --> - <string name="qr_code_scanner_title">QR code</string> - - <!-- QR Code Scanner description [CHAR LIMIT=NONE] --> - <string name="qr_code_scanner_description">Tap to scan</string> + <string name="qr_code_scanner_title">Scan QR code</string> <!-- Name of the work status bar icon. --> <string name="status_bar_work">Work profile</string> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java index db62f88325dc..e38d2bad11b3 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java @@ -17,36 +17,22 @@ package com.android.systemui.shared.system; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import android.app.ActivityOptions; import android.content.Context; import android.os.Handler; -import com.android.systemui.shared.recents.model.Task; - /** * Wrapper around internal ActivityOptions creation. */ public abstract class ActivityOptionsCompat { /** + * @Deprecated * @return ActivityOptions for starting a task in split screen as the primary window. */ public static ActivityOptions makeSplitScreenOptions(boolean dockTopLeft) { - return makeSplitScreenOptions(dockTopLeft, true); - } - - /** - * @return ActivityOptions for starting a task in split screen. - */ - public static ActivityOptions makeSplitScreenOptions(boolean dockTopLeft, boolean isPrimary) { - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchWindowingMode(isPrimary - ? WINDOWING_MODE_SPLIT_SCREEN_PRIMARY - : WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - return options; + return ActivityOptions.makeBasic(); } /** diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index 85d5de0ea4f6..32299f5643db 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -78,10 +78,6 @@ public class WindowManagerWrapper { public static final int WINDOWING_MODE_MULTI_WINDOW = WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; - public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = - WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; - public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = - WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; public static final int WINDOWING_MODE_FREEFORM = WindowConfiguration.WINDOWING_MODE_FREEFORM; public static final int ITYPE_EXTRA_NAVIGATION_BAR = InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; 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/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java index 28f21af5b56b..0529cdbcbb13 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java @@ -183,7 +183,7 @@ public class KeyguardPasswordViewController @Override void resetState() { mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser())); - mMessageAreaController.setMessage(R.string.keyguard_enter_your_password); + mMessageAreaController.setMessage(""); final boolean wasDisabled = mPasswordEntry.isEnabled(); mView.setPasswordEntryEnabled(true); mView.setPasswordEntryInputEnabled(true); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index 7635f919567a..41f92407a683 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -358,7 +358,7 @@ public class KeyguardPatternViewController } private void displayDefaultSecurityMessage() { - mMessageAreaController.setMessage(R.string.keyguard_enter_your_pattern); + mMessageAreaController.setMessage(""); } private void handleAttemptLockout(long elapsedRealtimeDeadline) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java index cc7e4f7a0d9a..f7423ed12e68 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java @@ -132,7 +132,6 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB @Override void resetState() { mView.setPasswordEntryEnabled(true); - mMessageAreaController.setMessage(R.string.keyguard_enter_your_pin); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java index 160d82af98fe..9f4585fb1a92 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java @@ -76,6 +76,12 @@ public class KeyguardPinViewController } @Override + void resetState() { + super.resetState(); + mMessageAreaController.setMessage(""); + } + + @Override public boolean startDisappearAnimation(Runnable finishRunnable) { return mView.startDisappearAnimation( mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 31f466f0fdf9..087817f0ec81 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -113,6 +113,22 @@ public class KeyguardStatusView extends GridLayout { } } + /** Sets a translationY value on every child view except for the media view. */ + public void setChildrenTranslationYExcludingMediaView(float translationY) { + setChildrenTranslationYExcluding(translationY, Set.of(mMediaHostContainer)); + } + + /** Sets a translationY value on every view except for the views in the provided set. */ + private void setChildrenTranslationYExcluding(float translationY, Set<View> excludedViews) { + for (int i = 0; i < mStatusViewContainer.getChildCount(); i++) { + final View child = mStatusViewContainer.getChildAt(i); + + if (!excludedViews.contains(child)) { + child.setTranslationY(translationY); + } + } + } + public float getChildrenAlphaExcludingSmartSpace() { return mChildrenAlphaExcludingSmartSpace; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index af3da9f940bd..14c9cb2022bc 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -137,6 +137,13 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV } /** + * Sets a translationY on the views on the keyguard, except on the media view. + */ + public void setTranslationYExcludingMedia(float translationY) { + mView.setChildrenTranslationYExcludingMediaView(translationY); + } + + /** * Set keyguard status view alpha. */ public void setAlpha(float alpha) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 1ef6dea4e680..3858f9cd7a82 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -326,7 +326,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private final Executor mBackgroundExecutor; private SensorPrivacyManager mSensorPrivacyManager; - private int mFaceAuthUserId; /** * Short delay before restarting fingerprint authentication after a successful try. This should @@ -1030,8 +1029,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab boolean cameraPrivacyEnabled = false; if (mSensorPrivacyManager != null) { cameraPrivacyEnabled = mSensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, - mFaceAuthUserId); + .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, + SensorPrivacyManager.Sensors.CAMERA); } if (msgId == FaceManager.FACE_ERROR_CANCELED @@ -2599,7 +2598,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // This would need to be updated for multi-sensor devices final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty() && mFaceSensorProperties.get(0).supportsFaceDetection; - mFaceAuthUserId = userId; if (isEncryptedOrLockdown(userId) && supportsFaceDetection) { mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId); } else { diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 370686a1e682..74659f71eb1f 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -558,7 +558,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme switch(event.getActionMasked()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_HOVER_ENTER: - if (!mDownDetected) { + if (!mDownDetected && mAccessibilityManager.isTouchExplorationEnabled()) { mVibrator.vibrate( Process.myUid(), getContext().getOpPackageName(), diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt index 4b868622ce58..498e71546bed 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt @@ -119,9 +119,13 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec if (useInvertedAlphaColor) { canvas.drawColor(bgColor) } + + // We may clear the color(if useInvertedAlphaColor is true) of the rounded corner rects + // before drawing rounded corners. If the cutout happens to be inside one of these rects, it + // will be cleared, so we have to draw rounded corners before cutout. + drawRoundedCorners(canvas) // Cutouts are drawn in DisplayCutoutBaseView.onDraw() super.onDraw(canvas) - drawRoundedCorners(canvas) debugTransparentRegionPaint?.let { calculateTransparentRect() 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/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 7e1a02626dc9..807ff21bf47a 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -254,8 +254,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorViewGeometryVsyncCallback = l -> { - if (isWindowVisible() && mMirrorSurface != null) { - calculateSourceBounds(mMagnificationFrame, mScale); + if (isWindowVisible() && mMirrorSurface != null && calculateSourceBounds( + mMagnificationFrame, mScale)) { // The final destination for the magnification surface should be at 0,0 // since the ViewRootImpl's position will change mTmpRect.set(0, 0, mMagnificationFrame.width(), @@ -350,6 +350,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorWindowControl.destroyControl(); } mMirrorViewBounds.setEmpty(); + mSourceBounds.setEmpty(); updateSystemUIStateIfNeeded(); mContext.unregisterComponentCallbacks(this); } @@ -728,8 +729,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold /** * Calculates the desired source bounds. This will be the area under from the center of the * displayFrame, factoring in scale. + * + * @return {@code true} if the source bounds is changed. */ - private void calculateSourceBounds(Rect displayFrame, float scale) { + private boolean calculateSourceBounds(Rect displayFrame, float scale) { + final Rect oldSourceBounds = mTmpRect; + oldSourceBounds.set(mSourceBounds); int halfWidth = displayFrame.width() / 2; int halfHeight = displayFrame.height() / 2; int left = displayFrame.left + (halfWidth - (int) (halfWidth / scale)); @@ -757,6 +762,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mSourceBounds.offsetTo(mSourceBounds.left, mWindowBounds.height() - mSourceBounds.height()); } + return !mSourceBounds.equals(oldSourceBounds); } private void calculateMagnificationFrameBoundary() { @@ -1079,7 +1085,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold pw.println(" mMagnificationFrame:" + (isWindowVisible() ? mMagnificationFrame : "empty")); pw.println(" mSourceBounds:" - + (isWindowVisible() ? mSourceBounds : "empty")); + + (mSourceBounds.isEmpty() ? "empty" : mSourceBounds)); pw.println(" mSystemGestureTop:" + mSystemGestureTop); pw.println(" mMagnificationFrameOffsetX:" + mMagnificationFrameOffsetX); pw.println(" mMagnificationFrameOffsetY:" + mMagnificationFrameOffsetY); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index bf42db53d3d8..bc7a3f6f4b13 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -584,16 +584,18 @@ public class UdfpsController implements DozeReceiver { } /** - * Play haptic to signal udfps scanning started. + * If a11y touchExplorationEnabled, play haptic to signal UDFPS scanning started. */ @VisibleForTesting public void playStartHaptic() { - mVibrator.vibrate( - Process.myUid(), - mContext.getOpPackageName(), - EFFECT_CLICK, - "udfps-onStart-click", - VIBRATION_ATTRIBUTES); + if (mAccessibilityManager.isTouchExplorationEnabled()) { + mVibrator.vibrate( + Process.myUid(), + mContext.getOpPackageName(), + EFFECT_CLICK, + "udfps-onStart-click", + VIBRATION_ATTRIBUTES); + } } @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java index 508262d4ddec..835025bbfc88 100644 --- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java +++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java @@ -16,6 +16,8 @@ package com.android.systemui.charging; +import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -76,6 +78,16 @@ public class WirelessChargingAnimation { } /** + * Creates a charging animation object using mostly default values for non-dozing and unknown + * battery level without charging number shown. + */ + public static WirelessChargingAnimation makeChargingAnimationWithNoBatteryLevel( + @NonNull Context context, UiEventLogger uiEventLogger) { + return makeWirelessChargingAnimation(context, null, + UNKNOWN_BATTERY_LEVEL, UNKNOWN_BATTERY_LEVEL, null, false, uiEventLogger); + } + + /** * Show the view for the specified duration. */ public void show(long delay) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index b8b4092ccf2f..dfb27eff722b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -89,6 +89,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private boolean mPaused = false; private boolean mScreenOff = false; private int mLastSensorValue = -1; + private DozeMachine.State mState = DozeMachine.State.UNINITIALIZED; /** * Debug value used for emulating various display brightness buckets: @@ -135,6 +136,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi @Override public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { + mState = newState; switch (newState) { case INITIALIZED: resetBrightnessToDefault(); @@ -262,8 +264,9 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi */ private int clampToDimBrightnessForScreenOff(int brightness) { final boolean screenTurningOff = - mDozeParameters.shouldClampToDimBrightness() - || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP; + (mDozeParameters.shouldClampToDimBrightness() + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP) + && mState == DozeMachine.State.INITIALIZED; if (screenTurningOff && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) { return Math.max( 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 2db3de173257..61cfe925f640 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -145,7 +145,7 @@ public class Flags { /***************************************/ // 900 - media public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true); - public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true); + public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false); public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, true); public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true); public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index c01d2c316a93..736e2e0e4035 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1706,14 +1706,6 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); return; } - - if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) { - if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted"); - // Without this, settings is not enabled until the lock screen first appears - setShowingLocked(false); - hideLocked(); - return; - } } if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 510d15bd7b73..ffdd5376b12e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -137,7 +137,6 @@ public class MediaControlPanel { private MediaCarouselController mMediaCarouselController; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final FalsingManager mFalsingManager; - private final MediaFlags mMediaFlags; // Used for swipe-to-dismiss logging. protected boolean mIsImpressed = false; @@ -156,7 +155,7 @@ public class MediaControlPanel { Lazy<MediaDataManager> lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, - FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) { + FalsingManager falsingManager, SystemClock systemClock) { mContext = context; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; @@ -167,7 +166,6 @@ public class MediaControlPanel { mMediaOutputDialogFactory = mediaOutputDialogFactory; mMediaCarouselController = mediaCarouselController; mFalsingManager = falsingManager; - mMediaFlags = mediaFlags; mSystemClock = systemClock; loadDimens(); @@ -506,9 +504,8 @@ public class MediaControlPanel { List<MediaAction> actionIcons = data.getActions(); List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); - // If the session actions flag is enabled, but we're still using the regular layout, use - // the session actions anyways - if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) { + // If we got session actions, use those instead + if (data.getSemanticActions() != null) { MediaButton semanticActions = data.getSemanticActions(); actionIcons = new ArrayList<MediaAction>(); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 9e14fe91f21d..ea92abd27e97 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -610,7 +610,8 @@ class MediaDataManager( var actionIcons: List<MediaAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() var semanticActions: MediaButton? = null - if (mediaFlags.areMediaSessionActionsEnabled() && mediaController.playbackState != null) { + if (mediaFlags.areMediaSessionActionsEnabled(sbn.packageName, sbn.user.identifier) && + mediaController.playbackState != null) { semanticActions = createActionsFromState(sbn.packageName, mediaController) } else { val actions = createActionsFromNotification(sbn) @@ -726,7 +727,7 @@ class MediaDataManager( } } - // Finally, assign the remaining button slots: C A play/pause B D + // Finally, assign the remaining button slots: play/pause A B C D // A = previous, else custom action (if not reserved) // B = next, else custom action (if not reserved) // C and D are always custom actions diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt index dd35a9a81399..f5200f9c8c93 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt @@ -16,6 +16,7 @@ package com.android.systemui.media +import android.app.StatusBarManager import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -26,16 +27,17 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) { /** * Check whether media control actions should be based on PlaybackState instead of notification */ - fun areMediaSessionActionsEnabled(): Boolean { - return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) + fun areMediaSessionActionsEnabled(packageName: String, userId: Int): Boolean { + val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, userId) + // Allow global override with flag + return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) } /** * Check whether media controls should use the new session-based layout */ fun useMediaSessionLayout(): Boolean { - return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) && - featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT) + return featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT) } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index 18b6699c80e9..7a4dee294dd6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -292,6 +292,18 @@ class MediaHierarchyManager @Inject constructor( } /** + * Returns the amount of translationY of the media container, during the current guided + * transformation, if running. If there is no guided transformation running, it will return 0. + */ + fun getGuidedTransformationTranslationY(): Int { + if (!isCurrentlyInGuidedTransformation()) { + return -1 + } + val startHost = getHost(previousLocation) ?: return 0 + return targetBounds.top - startHost.currentBounds.top + } + + /** * Is the shade currently collapsing from the expanded qs? If we're on the lockscreen and in qs, * we wouldn't want to transition in that case. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 0a4b68b501f7..eb209f723cb5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -192,6 +192,14 @@ class MediaHost constructor( } } + override var squishFraction: Float = 1.0f + set(value) { + if (!value.equals(field)) { + field = value + changedListener?.invoke() + } + } + override var showsOnlyActiveMedia: Boolean = false set(value) { if (!value.equals(field)) { @@ -242,6 +250,7 @@ class MediaHost constructor( override fun copy(): MediaHostState { val mediaHostState = MediaHostStateHolder() mediaHostState.expansion = expansion + mediaHostState.squishFraction = squishFraction mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia mediaHostState.measurementInput = measurementInput?.copy() mediaHostState.visible = visible @@ -260,6 +269,9 @@ class MediaHost constructor( if (expansion != other.expansion) { return false } + if (squishFraction != other.squishFraction) { + return false + } if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) { return false } @@ -278,6 +290,7 @@ class MediaHost constructor( override fun hashCode(): Int { var result = measurementInput?.hashCode() ?: 0 result = 31 * result + expansion.hashCode() + result = 31 * result + squishFraction.hashCode() result = 31 * result + falsingProtectionNeeded.hashCode() result = 31 * result + showsOnlyActiveMedia.hashCode() result = 31 * result + if (visible) 1 else 2 @@ -318,6 +331,11 @@ interface MediaHostState { var expansion: Float /** + * Fraction of the height animation. + */ + var squishFraction: Float + + /** * Is this host only showing active media or is it showing all of them including resumption? */ var showsOnlyActiveMedia: Boolean diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt index 591aad1014bd..a60016b23a7c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt @@ -18,13 +18,11 @@ package com.android.systemui.media import android.content.Context import android.content.res.Configuration +import androidx.annotation.VisibleForTesting import androidx.constraintlayout.widget.ConstraintSet import com.android.systemui.R import com.android.systemui.statusbar.policy.ConfigurationController -import com.android.systemui.util.animation.MeasurementOutput -import com.android.systemui.util.animation.TransitionLayout -import com.android.systemui.util.animation.TransitionLayoutController -import com.android.systemui.util.animation.TransitionViewState +import com.android.systemui.util.animation.* import javax.inject.Inject /** @@ -270,7 +268,6 @@ class MediaViewController @Inject constructor( TYPE.PLAYER_SESSION -> PlayerSessionViewHolder.gutsIds TYPE.RECOMMENDATION -> RecommendationViewHolder.gutsIds } - controlsIds.forEach { id -> viewState.widgetStates.get(id)?.let { state -> // Make sure to use the unmodified state if guts are not visible. @@ -282,59 +279,79 @@ class MediaViewController @Inject constructor( viewState.widgetStates.get(id)?.alpha = if (isGutsVisible) 1f else 0f viewState.widgetStates.get(id)?.gone = !isGutsVisible } - if (shouldHideGutsSettings) { viewState.widgetStates.get(R.id.settings)?.gone = true } } /** + * Apply squishFraction to a copy of viewState such that the cached version is untouched. + */ + private fun squishViewState(viewState: TransitionViewState, + squishFraction: Float): TransitionViewState { + val squishedViewState = viewState.copy() + squishedViewState.height = (squishedViewState.height * squishFraction).toInt() + val albumArtViewState = viewState.widgetStates.get(R.id.album_art) + if (albumArtViewState != null) { + albumArtViewState.height = squishedViewState.height + } + return squishedViewState; + } + + /** * Obtain a new viewState for a given media state. This usually returns a cached state, but if * it's not available, it will recreate one by measuring, which may be expensive. */ - private fun obtainViewState(state: MediaHostState?): TransitionViewState? { + @VisibleForTesting + public fun obtainViewState(state: MediaHostState?): TransitionViewState? { if (state == null || state.measurementInput == null) { return null } // Only a subset of the state is relevant to get a valid viewState. Let's get the cachekey var cacheKey = getKey(state, isGutsVisible, tmpKey) val viewState = viewStates[cacheKey] + if (viewState != null) { // we already have cached this measurement, let's continue + if (state.squishFraction < 1f) { + return squishViewState(viewState, state.squishFraction); + } return viewState } // Copy the key since this might call recursively into it and we're using tmpKey cacheKey = cacheKey.copy() val result: TransitionViewState? - if (transitionLayout != null) { - // Let's create a new measurement - if (state.expansion == 0.0f || state.expansion == 1.0f) { - result = transitionLayout!!.calculateViewState( - state.measurementInput!!, - constraintSetForExpansion(state.expansion), - TransitionViewState()) - - setGutsViewState(result) - // We don't want to cache interpolated or null states as this could quickly fill up - // our cache. We only cache the start and the end states since the interpolation - // is cheap - viewStates[cacheKey] = result - } else { - // This is an interpolated state - val startState = state.copy().also { it.expansion = 0.0f } - - // Given that we have a measurement and a view, let's get (guaranteed) viewstates - // from the start and end state and interpolate them - val startViewState = obtainViewState(startState) as TransitionViewState - val endState = state.copy().also { it.expansion = 1.0f } - val endViewState = obtainViewState(endState) as TransitionViewState - result = layoutController.getInterpolatedState( - startViewState, - endViewState, - state.expansion) - } + if (transitionLayout == null) { + return null + } + // Not cached. Let's create a new measurement + if (state.expansion == 0.0f || state.expansion == 1.0f) { + result = transitionLayout!!.calculateViewState( + state.measurementInput!!, + constraintSetForExpansion(state.expansion), + TransitionViewState()) + // We don't want to cache interpolated or null states as this could quickly fill up + // our cache. We only cache the start and the end states since the interpolation + // is cheap + setGutsViewState(result) + viewStates[cacheKey] = result } else { - result = null + // This is an interpolated state + val startState = state.copy().also { it.expansion = 0.0f } + + // Given that we have a measurement and a view, let's get (guaranteed) viewstates + // from the start and end state and interpolate them + val startViewState = obtainViewState(startState) as TransitionViewState + val endState = state.copy().also { it.expansion = 1.0f } + + val endViewState = obtainViewState(endState) as TransitionViewState + result = layoutController.getInterpolatedState( + startViewState, + endViewState, + state.expansion) + } + if (state.squishFraction < 1f) { + return squishViewState(result, state.squishFraction); } return result } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index c96aca37987b..62d5c8e51005 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -34,7 +34,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; -import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.TextView; @@ -129,7 +128,7 @@ public abstract class MediaOutputBaseAdapter extends final ImageView mTitleIcon; final ProgressBar mProgressBar; final SeekBar mSeekBar; - final RelativeLayout mTwoLineLayout; + final LinearLayout mTwoLineLayout; final ImageView mStatusIcon; final CheckBox mCheckBox; private String mDeviceId; diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt index 9cd97ff8e343..2a6ca1acb38e 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt @@ -22,13 +22,14 @@ import android.widget.ImageView import android.widget.LinearLayout import com.android.settingslib.Utils import com.android.systemui.R +import com.android.systemui.statusbar.events.BackgroundAnimatableView class OngoingPrivacyChip @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttrs: Int = 0, defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyleAttrs, defStyleRes) { +) : FrameLayout(context, attrs, defStyleAttrs, defStyleRes), BackgroundAnimatableView { private var iconMargin = 0 private var iconSize = 0 @@ -50,6 +51,16 @@ class OngoingPrivacyChip @JvmOverloads constructor( updateResources() } + /** + * When animating as a chip in the status bar, we want to animate the width for the container + * of the privacy items. We have to subtract our own top and left offset because the bounds + * come to us as absolute on-screen bounds, and `iconsContainer` is laid out relative to the + * frame layout's bounds. + */ + override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) { + iconsContainer.setLeftTopRightBottom(l - left, t - top, r - left, b - top) + } + // Should only be called if the builder icons or app changed private fun updateView(builder: PrivacyChipBuilder) { fun setIcons(chipBuilder: PrivacyChipBuilder, iconsContainer: ViewGroup) { diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java b/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java index e26c768a5e80..8000bdccfa68 100644 --- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java +++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java @@ -160,14 +160,15 @@ public class QRCodeScannerController implements * Returns true if lock screen entry point for QR Code Scanner is to be enabled. */ public boolean isEnabledForLockScreenButton() { - return mQRCodeScannerEnabled && mIntent != null && mConfigEnableLockScreenButton; + return mQRCodeScannerEnabled && mIntent != null && mConfigEnableLockScreenButton + && isActivityCallable(mIntent); } /** * Returns true if quick settings entry point for QR Code Scanner is to be enabled. */ public boolean isEnabledForQuickSettings() { - return mIntent != null; + return mIntent != null && isActivityCallable(mIntent); } /** @@ -278,7 +279,7 @@ public class QRCodeScannerController implements intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); } - if (isActivityCallable(intent)) { + if (isActivityAvailable(intent)) { mQRCodeScannerActivity = qrCodeScannerActivity; mComponentName = componentName; mIntent = intent; @@ -293,7 +294,7 @@ public class QRCodeScannerController implements } } - private boolean isActivityCallable(Intent intent) { + private boolean isActivityAvailable(Intent intent) { // Our intent should always be explicit and should have a component set if (intent.getComponent() == null) return false; @@ -307,6 +308,17 @@ public class QRCodeScannerController implements flags).isEmpty(); } + private boolean isActivityCallable(Intent intent) { + // Our intent should always be explicit and should have a component set + if (intent.getComponent() == null) return false; + + int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE + | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; + return !mContext.getPackageManager().queryIntentActivities(intent, + flags).isEmpty(); + } + private void unregisterUserChangeObservers() { mUserTracker.removeCallback(mUserChangedListener); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index d1b569f7f438..4640205c82f5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -241,7 +241,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private void addNonFirstPageAnimators(int page) { Pair<HeightExpansionAnimator, TouchAnimator> pair = createSecondaryPageAnimators(page); - mNonFirstPageQSAnimators.put(page, pair); + if (pair != null) { + // pair is null in one of two cases: + // * mPagedTileLayout is null, meaning we are still setting up. + // * the page has no tiles + // In either case, don't add the animators to the map. + mNonFirstPageQSAnimators.put(page, pair); + } } @Override @@ -518,6 +524,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha SideLabelTileLayout qqsLayout = (SideLabelTileLayout) mQuickQsPanel.getTileLayout(); View view = mQs.getView(); List<String> specs = mPagedLayout.getSpecsForPage(page); + if (specs.isEmpty()) { + // specs should not be empty in a valid secondary page, as we scrolled to it. + // We may crash later on because there's a null animator. + specs = mQsPanelController.getHost().mTileSpecs; + Log.e(TAG, "Trying to create animators for empty page " + page + ". Tiles: " + specs); + // return null; + } int row = -1; int lastTileTop = -1; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 3ef72202a591..fe8c309ad2f3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -573,6 +573,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca if (mQSAnimator != null) { mQSAnimator.setPosition(expansion); } + mQqsMediaHost.setSquishFraction(mSquishinessFraction); updateMediaPositions(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 8c08873b9ab6..f2dd7700e65e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -102,7 +102,7 @@ public class QuickStatusBarHeader extends FrameLayout { private int mTopViewMeasureHeight; @NonNull - private List<String> mRssiIgnoredSlots; + private List<String> mRssiIgnoredSlots = List.of(); private boolean mIsSingleCarrier; private boolean mHasCenterCutout; diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java index 32515a258b46..4cacbbacec2f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java @@ -15,26 +15,22 @@ */ package com.android.systemui.qs.external; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Icon; import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.service.quicksettings.IQSService; import android.service.quicksettings.Tile; -import android.service.quicksettings.TileService; import android.util.ArrayMap; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.statusbar.StatusBarIcon; @@ -42,6 +38,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.QSTileHost; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -51,6 +48,7 @@ import java.util.Comparator; import java.util.Objects; import javax.inject.Inject; +import javax.inject.Provider; /** * Runs the day-to-day operations of which tiles should be bound and when. @@ -64,11 +62,12 @@ public class TileServices extends IQSService.Stub { private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>(); private final ArrayMap<IBinder, CustomTile> mTokenMap = new ArrayMap<>(); private final Context mContext; - private final Handler mHandler; private final Handler mMainHandler; + private final Provider<Handler> mHandlerProvider; private final QSTileHost mHost; private final KeyguardStateController mKeyguardStateController; private final BroadcastDispatcher mBroadcastDispatcher; + private final CommandQueue mCommandQueue; private final UserTracker mUserTracker; private int mMaxBound = DEFAULT_MAX_BOUND; @@ -76,23 +75,20 @@ public class TileServices extends IQSService.Stub { @Inject public TileServices( QSTileHost host, - @Main Looper looper, + @Main Provider<Handler> handlerProvider, BroadcastDispatcher broadcastDispatcher, UserTracker userTracker, - KeyguardStateController keyguardStateController) { + KeyguardStateController keyguardStateController, + CommandQueue commandQueue) { mHost = host; mKeyguardStateController = keyguardStateController; mContext = mHost.getContext(); mBroadcastDispatcher = broadcastDispatcher; - mHandler = new Handler(looper); - mMainHandler = new Handler(Looper.getMainLooper()); + mHandlerProvider = handlerProvider; + mMainHandler = mHandlerProvider.get(); mUserTracker = userTracker; - mBroadcastDispatcher.registerReceiver( - mRequestListeningReceiver, - new IntentFilter(TileService.ACTION_REQUEST_LISTENING), - null, // Use the default Executor - UserHandle.ALL - ); + mCommandQueue = commandQueue; + mCommandQueue.addCallback(mRequestListeningCallback); } public Context getContext() { @@ -118,7 +114,7 @@ public class TileServices extends IQSService.Stub { protected TileServiceManager onCreateTileService(ComponentName component, BroadcastDispatcher broadcastDispatcher) { - return new TileServiceManager(this, mHandler, component, + return new TileServiceManager(this, mHandlerProvider.get(), component, broadcastDispatcher, mUserTracker); } @@ -354,21 +350,14 @@ public class TileServices extends IQSService.Stub { public void destroy() { synchronized (mServices) { mServices.values().forEach(service -> service.handleDestroy()); - mBroadcastDispatcher.unregisterReceiver(mRequestListeningReceiver); } + mCommandQueue.removeCallback(mRequestListeningCallback); } - private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() { + private final CommandQueue.Callbacks mRequestListeningCallback = new CommandQueue.Callbacks() { @Override - public void onReceive(Context context, Intent intent) { - if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) { - try { - ComponentName c = intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME); - requestListening(c); - } catch (ClassCastException ex) { - Log.e(TAG, "Bad component name", ex); - } - } + public void requestTileServiceListeningState(@NonNull ComponentName componentName) { + mMainHandler.post(() -> requestListening(componentName)); } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java index b65802506cbf..b41502213555 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java @@ -117,7 +117,6 @@ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { state.icon = ResourceIcon.get(R.drawable.ic_qr_code_scanner); state.state = mQRCodeScannerController.isEnabledForQuickSettings() ? Tile.STATE_ACTIVE : Tile.STATE_UNAVAILABLE; - state.secondaryLabel = mContext.getString(R.string.qr_code_scanner_description); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 5932a64c1c71..d9a98b165795 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -163,6 +163,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_MEDIA_TRANSFER_RECEIVER_STATE = 65 << MSG_SHIFT; private static final int MSG_REGISTER_NEARBY_MEDIA_DEVICE_PROVIDER = 66 << MSG_SHIFT; private static final int MSG_UNREGISTER_NEARBY_MEDIA_DEVICE_PROVIDER = 67 << MSG_SHIFT; + private static final int MSG_TILE_SERVICE_REQUEST_LISTENING_STATE = 68 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; @@ -433,6 +434,11 @@ public class CommandQueue extends IStatusBar.Stub implements default void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {} /** + * @see IStatusBar#requestTileServiceListeningState + */ + default void requestTileServiceListeningState(@NonNull ComponentName componentName) {} + + /** * @see IStatusBar#requestAddTile */ default void requestAddTile( @@ -1190,6 +1196,12 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override + public void requestTileServiceListeningState(@NonNull ComponentName componentName) { + mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_LISTENING_STATE, componentName) + .sendToTarget(); + } + + @Override public void requestAddTile( @NonNull ComponentName componentName, @NonNull CharSequence appName, @@ -1686,6 +1698,12 @@ public class CommandQueue extends IStatusBar.Stub implements mCallbacks.get(i).unregisterNearbyMediaDevicesProvider(provider); } break; + case MSG_TILE_SERVICE_REQUEST_LISTENING_STATE: + ComponentName component = (ComponentName) msg.obj; + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).requestTileServiceListeningState(component); + } + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index ccec0c2d58cc..16ddb0a7e1a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -293,6 +293,14 @@ public class KeyguardIndicationController { } } + /** + * Cleanup + */ + public void destroy() { + mHandler.removeCallbacksAndMessages(null); + mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver); + } + private void handleAlignStateChanged(int alignState) { String alignmentIndication = ""; if (alignState == DockManager.ALIGN_STATE_POOR) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index 1ab03455cca2..ab4d0dd355f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -406,6 +406,7 @@ class LockscreenShadeTransitionController @Inject constructor( mediaHierarchyManager.setTransitionToFullShadeAmount(field) transitionToShadeAmountCommon(field) + transitionToShadeAmountKeyguard(field) } } } @@ -420,11 +421,6 @@ class LockscreenShadeTransitionController @Inject constructor( val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance) scrimController.setTransitionToFullShadeProgress(scrimProgress) - // Fade out all content only visible on the lockscreen - val npvcProgress = - MathUtils.saturate(dragDownAmount / npvcKeyguardContentAlphaTransitionDistance) - notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - npvcProgress) - if (depthControllerTransitionDistance > 0) { val depthProgress = MathUtils.saturate(dragDownAmount / depthControllerTransitionDistance) @@ -438,6 +434,22 @@ class LockscreenShadeTransitionController @Inject constructor( centralSurfaces.setTransitionToFullShadeProgress(statusBarProgress) } + private fun transitionToShadeAmountKeyguard(dragDownAmount: Float) { + // Fade out all content only visible on the lockscreen + val keyguardAlphaProgress = + MathUtils.saturate(dragDownAmount / npvcKeyguardContentAlphaTransitionDistance) + val keyguardAlpha = 1f - keyguardAlphaProgress + val keyguardTranslationY = if (useSplitShade) { + // On split-shade, the translationY of the keyguard should stay in sync with the + // translation of media. + mediaHierarchyManager.getGuidedTransformationTranslationY() + } else { + 0 + } + notificationPanelController + .setKeyguardTransitionProgress(keyguardAlpha, keyguardTranslationY) + } + private fun setDragDownAmountAnimated( target: Float, delay: Long = 0, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 94a6d3e99842..66c1d87fb812 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -507,12 +507,11 @@ public class NotificationRemoteInputManager implements Dumpable { Math.max(cx + cy, cx + (h - cy)), Math.max((w - cx) + cy, (w - cx) + (h - cy))); - riv.setRevealParameters(cx, cy, r); - riv.setPendingIntent(pendingIntent); + riv.getController().setRevealParams(new RemoteInputView.RevealParams(cx, cy, r)); riv.getController().setPendingIntent(pendingIntent); - riv.setRemoteInput(inputs, input, editedSuggestionInfo); riv.getController().setRemoteInput(input); riv.getController().setRemoteInputs(inputs); + riv.getController().setEditedSuggestionInfo(editedSuggestionInfo); riv.focusAnimated(); if (userMessageContent != null) { riv.setEditTextContent(userMessageContent); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt index d4d84c138b20..4e1404d0637b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.events +import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.graphics.drawable.ColorDrawable @@ -27,13 +28,15 @@ import com.android.systemui.R import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyItem +typealias ViewCreator = (context: Context) -> BackgroundAnimatableView + interface StatusEvent { val priority: Int // Whether or not to force the status bar open and show a dot val forceVisible: Boolean // Whether or not to show an animation for this event val showAnimation: Boolean - val viewCreator: (context: Context) -> View + val viewCreator: ViewCreator var contentDescription: String? // Update this event with values from another event. @@ -47,14 +50,37 @@ interface StatusEvent { } } +class BGView( + context: Context +) : View(context), BackgroundAnimatableView { + override val view: View + get() = this + + override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) { + setLeftTopRightBottom(l, t, r, b) + } +} + +@SuppressLint("AppCompatCustomView") +class BGImageView( + context: Context +) : ImageView(context), BackgroundAnimatableView { + override val view: View + get() = this + + override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) { + setLeftTopRightBottom(l, t, r, b) + } +} + class BatteryEvent : StatusEvent { override val priority = 50 override val forceVisible = false override val showAnimation = true override var contentDescription: String? = "" - override val viewCreator: (context: Context) -> View = { context -> - val iv = ImageView(context) + override val viewCreator: (context: Context) -> BGImageView = { context -> + val iv = BGImageView(context) iv.setImageDrawable(ThemedBatteryDrawable(context, Color.WHITE)) iv.setBackgroundDrawable(ColorDrawable(Color.GREEN)) iv @@ -72,7 +98,7 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent { var privacyItems: List<PrivacyItem> = listOf() private var privacyChip: OngoingPrivacyChip? = null - override val viewCreator: (context: Context) -> View = { context -> + override val viewCreator: ViewCreator = { context -> val v = LayoutInflater.from(context) .inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip v.privacyList = privacyItems @@ -82,7 +108,7 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent { } override fun toString(): String { - return javaClass.simpleName + return "${javaClass.simpleName}(forceVisible=$forceVisible, privacyItems=$privacyItems)" } override fun shouldUpdateFromEvent(other: StatusEvent?): Boolean { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt index d5a0467c9b9e..9795dcf1fcd8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt @@ -18,14 +18,16 @@ package com.android.systemui.statusbar.events import android.animation.ValueAnimator import android.content.Context +import android.graphics.Point import android.view.Gravity import android.view.LayoutInflater import android.view.View +import android.view.View.MeasureSpec.AT_MOST import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.FrameLayout import com.android.systemui.R -import com.android.systemui.statusbar.phone.StatusBarLocationPublisher +import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider import com.android.systemui.statusbar.window.StatusBarWindowController import javax.inject.Inject @@ -35,44 +37,73 @@ import javax.inject.Inject class SystemEventChipAnimationController @Inject constructor( private val context: Context, private val statusBarWindowController: StatusBarWindowController, - private val locationPublisher: StatusBarLocationPublisher + private val contentInsetsProvider: StatusBarContentInsetsProvider ) : SystemStatusChipAnimationCallback { - var showPersistentDot = false - set(value) { - field = value - statusBarWindowController.setForceStatusBarVisible(value) - maybeUpdateShowDot() - } private lateinit var animationWindowView: FrameLayout - private lateinit var animationDotView: View - private var currentAnimatedView: View? = null + + private var currentAnimatedView: BackgroundAnimatableView? = null + + // Left for LTR, Right for RTL + private var animationDirection = LEFT + private var chipRight = 0 + private var chipLeft = 0 + private var chipWidth = 0 + private var dotCenter = Point(0, 0) + private var dotSize = context.resources.getDimensionPixelSize( + R.dimen.ongoing_appops_dot_diameter) + // If the chip animates away to a persistent dot, then we modify the CHIP_OUT animation + private var isAnimatingToDot = false // TODO: move to dagger private var initialized = false override fun onChipAnimationStart( - viewCreator: (context: Context) -> View, + viewCreator: ViewCreator, @SystemAnimationState state: Int ) { if (!initialized) init() if (state == ANIMATING_IN) { - currentAnimatedView = viewCreator(context) - animationWindowView.addView(currentAnimatedView, layoutParamsDefault()) + animationDirection = if (animationWindowView.isLayoutRtl) RIGHT else LEFT + + // Initialize the animated view + val insets = contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation() + currentAnimatedView = viewCreator(context).also { + animationWindowView.addView( + it.view, + layoutParamsDefault( + if (animationWindowView.isLayoutRtl) insets.first + else insets.second)) + it.view.alpha = 0f + // For some reason, the window view's measured width is always 0 here, so use the + // parent (status bar) + it.view.measure( + View.MeasureSpec.makeMeasureSpec( + (animationWindowView.parent as View).width, AT_MOST), + View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST)) + chipWidth = it.chipWidth + } + + // decide which direction we're animating from, and then set some screen coordinates + val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation() + when (animationDirection) { + LEFT -> { + chipRight = contentRect.right + chipLeft = contentRect.right - chipWidth + } + else /* RIGHT */ -> { + chipLeft = contentRect.left + chipRight = contentRect.left + chipWidth + } + } - // We are animating IN; chip comes in from View.END currentAnimatedView?.apply { - val translation = width.toFloat() - translationX = if (isLayoutRtl) -translation else translation - alpha = 0f - visibility = View.VISIBLE - setPadding(locationPublisher.marginLeft, 0, locationPublisher.marginRight, 0) + updateAnimatedViewBoundsForAmount(0.1f, this) } } else { // We are animating away - currentAnimatedView?.apply { - translationX = 0f + currentAnimatedView!!.view.apply { alpha = 1f } } @@ -82,15 +113,14 @@ class SystemEventChipAnimationController @Inject constructor( if (state == ANIMATING_IN) { // Finished animating in currentAnimatedView?.apply { - translationX = 0f - alpha = 1f + updateAnimatedViewBoundsForAmount(1f, this) } } else { // Finished animating away - currentAnimatedView?.apply { + currentAnimatedView!!.view.apply { visibility = View.INVISIBLE } - animationWindowView.removeView(currentAnimatedView) + animationWindowView.removeView(currentAnimatedView!!.view) } } @@ -98,22 +128,10 @@ class SystemEventChipAnimationController @Inject constructor( animator: ValueAnimator, @SystemAnimationState state: Int ) { - // Alpha is parameterized 0,1, and translation from (width, 0) currentAnimatedView?.apply { - val amt = animator.animatedValue as Float - - alpha = amt - - val w = width - val translation = (1 - amt) * w - translationX = if (isLayoutRtl) -translation else translation - } - } - - private fun maybeUpdateShowDot() { - if (!initialized) return - if (!showPersistentDot && currentAnimatedView == null) { - animationDotView.visibility = View.INVISIBLE + val amt = (animator.animatedValue as Float).amt() + view.alpha = (animator.animatedValue as Float) + updateAnimatedViewBoundsForAmount(amt, this) } } @@ -121,19 +139,56 @@ class SystemEventChipAnimationController @Inject constructor( initialized = true animationWindowView = LayoutInflater.from(context) .inflate(R.layout.system_event_animation_window, null) as FrameLayout - animationDotView = animationWindowView.findViewById(R.id.dot_view) val lp = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) lp.gravity = Gravity.END or Gravity.CENTER_VERTICAL statusBarWindowController.addViewToWindow(animationWindowView, lp) + animationWindowView.clipToPadding = false + animationWindowView.clipChildren = false + animationWindowView.measureAllChildren = true } - private fun start() = if (animationWindowView.isLayoutRtl) right() else left() - private fun right() = locationPublisher.marginRight - private fun left() = locationPublisher.marginLeft + private fun layoutParamsDefault(marginEnd: Int): FrameLayout.LayoutParams = + FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).also { + it.gravity = Gravity.END or Gravity.CENTER_VERTICAL + it.marginEnd = marginEnd + } - private fun layoutParamsDefault(): FrameLayout.LayoutParams = - FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).also { - it.gravity = Gravity.END or Gravity.CENTER_VERTICAL - it.marginStart = start() + private fun updateAnimatedViewBoundsForAmount(amt: Float, chip: BackgroundAnimatableView) { + when (animationDirection) { + LEFT -> { + chip.setBoundsForAnimation( + (chipRight - (chipWidth * amt)).toInt(), + chip.view.top, + chipRight, + chip.view.bottom) + } + else /* RIGHT */ -> { + chip.setBoundsForAnimation( + chipLeft, + chip.view.top, + (chipLeft + (chipWidth * amt)).toInt(), + chip.view.bottom) + } + } } + + private fun start() = if (animationWindowView.isLayoutRtl) right() else left() + private fun right() = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation().right + private fun left() = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation().left + private fun Float.amt() = 0.01f.coerceAtLeast(this) +} + +/** + * Chips should provide a view that can be animated with something better than a fade-in + */ +interface BackgroundAnimatableView { + val view: View // Since this can't extend View, add a view prop + get() = this as View + val chipWidth: Int + get() = view.measuredWidth + fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) } + +// Animation directions +private const val LEFT = 1 +private const val RIGHT = 2 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt index 04f7492e8562..fde5d39db7e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt @@ -70,11 +70,11 @@ class SystemEventCoordinator @Inject constructor( fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) { val event = PrivacyEvent(showAnimation) event.privacyItems = privacyStateListener.currentPrivacyItems - event.contentDescription = { + event.contentDescription = run { val items = PrivacyChipBuilder(context, event.privacyItems).joinTypes() context.getString( R.string.ongoing_privacy_chip_content_multiple_apps, items) - }() + } scheduler.onStatusEvent(event) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt index 5a273294e87c..947f3eb2ee12 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt @@ -21,12 +21,12 @@ import android.animation.AnimatorListenerAdapter import android.animation.AnimatorSet import android.animation.ValueAnimator import android.annotation.IntDef -import android.content.Context import android.os.Process import android.provider.DeviceConfig import android.util.Log -import android.view.View import com.android.systemui.Dumpable +import com.android.systemui.animation.Interpolators.STANDARD_ACCELERATE +import com.android.systemui.animation.Interpolators.STANDARD_DECELERATE import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main @@ -45,7 +45,7 @@ import javax.inject.Inject * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD): * - Avoiding log spam by only allowing 12 events per minute (1event/5s) * - Waits 100ms to schedule any event for debouncing/prioritization - * - Simple prioritization: Privacy > Battery > connectivity (encoded in StatusEvent) + * - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent]) * - Only schedules a single event, and throws away lowest priority events * * There are 4 basic stages of animation at play here: @@ -111,7 +111,7 @@ class SystemStatusAnimationScheduler @Inject constructor( scheduleEvent(event) } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) { if (DEBUG) { - Log.d(TAG, "updating current event from: $event") + Log.d(TAG, "updating current event from: $event. animationState=$animationState") } scheduledEvent?.updateFromEvent(event) if (event.forceVisible) { @@ -172,12 +172,14 @@ class SystemStatusAnimationScheduler @Inject constructor( entranceAnimator.duration = ENTRANCE_ANIM_LENGTH entranceAnimator.addListener(systemAnimatorAdapter) entranceAnimator.addUpdateListener(systemUpdateListener) + entranceAnimator.interpolator = STANDARD_ACCELERATE val chipAnimator = ValueAnimator.ofFloat(0f, 1f) chipAnimator.duration = CHIP_ANIM_LENGTH chipAnimator.addListener( ChipAnimatorAdapter(RUNNING_CHIP_ANIM, scheduledEvent!!.viewCreator)) chipAnimator.addUpdateListener(chipUpdateListener) + chipAnimator.interpolator = STANDARD_DECELERATE val aSet2 = AnimatorSet() aSet2.playSequentially(entranceAnimator, chipAnimator) @@ -190,6 +192,12 @@ class SystemStatusAnimationScheduler @Inject constructor( systemAnimator.duration = ENTRANCE_ANIM_LENGTH systemAnimator.addListener(systemAnimatorAdapter) systemAnimator.addUpdateListener(systemUpdateListener) + systemAnimator.interpolator = STANDARD_DECELERATE + systemAnimator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + statusBarWindowController.setForceStatusBarVisible(false) + } + }) val chipAnimator = ValueAnimator.ofFloat(1f, 0f) chipAnimator.duration = CHIP_ANIM_LENGTH @@ -201,6 +209,7 @@ class SystemStatusAnimationScheduler @Inject constructor( chipAnimator.addListener( ChipAnimatorAdapter(endState, scheduledEvent!!.viewCreator)) chipAnimator.addUpdateListener(chipUpdateListener) + chipAnimator.interpolator = STANDARD_ACCELERATE val aSet2 = AnimatorSet() @@ -212,7 +221,6 @@ class SystemStatusAnimationScheduler @Inject constructor( aSet2.start() - statusBarWindowController.setForceStatusBarVisible(false) scheduledEvent = null }, DISPLAY_LENGTH) }, DELAY) @@ -313,7 +321,7 @@ class SystemStatusAnimationScheduler @Inject constructor( inner class ChipAnimatorAdapter( @SystemAnimationState val endState: Int, - val viewCreator: (context: Context) -> View + val viewCreator: ViewCreator ) : AnimatorListenerAdapter() { override fun onAnimationEnd(p0: Animator?) { chipAnimationController.onChipAnimationEnd(animationState) @@ -359,7 +367,7 @@ interface SystemStatusChipAnimationCallback { fun onChipAnimationUpdate(animator: ValueAnimator, @SystemAnimationState state: Int) {} fun onChipAnimationStart( - viewCreator: (context: Context) -> View, + viewCreator: ViewCreator, @SystemAnimationState state: Int ) {} @@ -371,7 +379,7 @@ interface SystemStatusChipAnimationCallback { @Retention(AnnotationRetention.SOURCE) @IntDef( value = [ - IDLE, ANIMATING_IN, RUNNING_CHIP_ANIM, ANIMATING_OUT + IDLE, ANIMATING_IN, RUNNING_CHIP_ANIM, ANIMATING_OUT, SHOWING_PERSISTENT_DOT ] ) annotation class SystemAnimationState diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index 5b7d90bfca44..df412ed93f55 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -16,11 +16,9 @@ package com.android.systemui.statusbar.notification; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import android.annotation.NonNull; import android.annotation.Nullable; @@ -182,25 +180,6 @@ public class InstantAppNotifier extends CoreStartable } /** - * Posts an instant app notification if the top activity of the primary container in the - * splitted screen is an instant app and the corresponding instant app notification is not - * posted yet. If the notification already exists, this method removes it from {@code - * notifs} in the arguments. - */ - private void checkAndPostForPrimaryScreen( - @NonNull ArraySet<Pair<String, Integer>> notifs, - @NonNull NotificationManager noMan, - @NonNull IPackageManager pm) { - try { - final RootTaskInfo info = ActivityTaskManager.getService().getRootTaskInfo( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED); - checkAndPostForStack(info, notifs, noMan, pm); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - /** * Posts an instant app notification if the top activity of the given stack is an instant app * and the corresponding instant app notification is not posted yet. If the notification already * exists, this method removes it from {@code notifs} in the arguments. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt index 2c1296f34a42..7fbb0f1182c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt @@ -22,15 +22,18 @@ class NotificationLaunchAnimatorControllerProvider @Inject constructor( private val headsUpManager: HeadsUpManagerPhone, private val jankMonitor: InteractionJankMonitor ) { + @JvmOverloads fun getAnimatorController( - notification: ExpandableNotificationRow + notification: ExpandableNotificationRow, + onFinishAnimationCallback: Runnable = Runnable {} ): NotificationLaunchAnimatorController { return NotificationLaunchAnimatorController( notificationShadeWindowViewController, notificationListContainer, headsUpManager, notification, - jankMonitor + jankMonitor, + onFinishAnimationCallback ) } } @@ -45,7 +48,8 @@ class NotificationLaunchAnimatorController( private val notificationListContainer: NotificationListContainer, private val headsUpManager: HeadsUpManagerPhone, private val notification: ExpandableNotificationRow, - private val jankMonitor: InteractionJankMonitor + private val jankMonitor: InteractionJankMonitor, + private val onFinishAnimationCallback: Runnable ) : ActivityLaunchAnimator.Controller { companion object { @@ -119,6 +123,7 @@ class NotificationLaunchAnimatorController( if (!willAnimate) { removeHun(animate = true) + onFinishAnimationCallback.run() } } @@ -137,6 +142,7 @@ class NotificationLaunchAnimatorController( notificationShadeWindowViewController.setExpandAnimationRunning(false) notificationEntry.isExpandAnimationRunning = false removeHun(animate = true) + onFinishAnimationCallback.run() } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { @@ -156,6 +162,7 @@ class NotificationLaunchAnimatorController( notificationListContainer.setExpandingNotification(null) applyParams(null) removeHun(animate = false) + onFinishAnimationCallback.run() } private fun applyParams(params: ExpandAnimationParameters?) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index 0df2162d3338..da0169bd6dc4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -72,10 +72,11 @@ class HeadsUpCoordinator @Inject constructor( private var mEndLifetimeExtension: OnEndLifetimeExtensionCallback? = null private lateinit var mNotifPipeline: NotifPipeline private var mNow: Long = -1 - // notifs we've extended the lifetime for - private val mNotifsExtendingLifetime = ArraySet<NotificationEntry>() private val mPostedEntries = LinkedHashMap<String, PostedEntry>() + // notifs we've extended the lifetime for with cancellation callbacks + private val mNotifsExtendingLifetime = ArrayMap<NotificationEntry, Runnable?>() + override fun attach(pipeline: NotifPipeline) { mNotifPipeline = pipeline mHeadsUpManager.addListener(mOnHeadsUpChangedListener) @@ -460,23 +461,20 @@ class HeadsUpCoordinator @Inject constructor( } if (isSticky(entry)) { val removeAfterMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key) - mExecutor.executeDelayed({ - val canStillRemove = mHeadsUpManager.canRemoveImmediately(entry.key) - if (mNotifsExtendingLifetime.contains(entry) && canStillRemove) { - mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ true) - } + mNotifsExtendingLifetime[entry] = mExecutor.executeDelayed({ + mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ true) }, removeAfterMillis) } else { mExecutor.execute { mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ false) } + mNotifsExtendingLifetime[entry] = null } - mNotifsExtendingLifetime.add(entry) return true } override fun cancelLifetimeExtension(entry: NotificationEntry) { - mNotifsExtendingLifetime.remove(entry) + mNotifsExtendingLifetime.remove(entry)?.run() } } @@ -543,7 +541,8 @@ class HeadsUpCoordinator @Inject constructor( mPostedEntries[entry.key]?.calculateShouldBeHeadsUpStrict ?: isAttemptingToShowHun(entry) private fun endNotifLifetimeExtensionIfExtended(entry: NotificationEntry) { - if (mNotifsExtendingLifetime.remove(entry)) { + if (mNotifsExtendingLifetime.contains(entry)) { + mNotifsExtendingLifetime.remove(entry)?.run() mEndLifetimeExtension?.onEndLifetimeExtension(mLifetimeExtender, entry) } } 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/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java index cd2affead92a..7c4e4499dca6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java @@ -73,7 +73,7 @@ public class NotificationGroupManagerLegacy implements GroupExpansionManager, Dumpable { - private static final String TAG = "NotifGroupManager"; + private static final String TAG = "LegacyNotifGroupManager"; private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG); private static final boolean SPEW = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE); /** 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/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 9cb5dc5d4aa4..adb4ce68c031 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -413,7 +413,10 @@ public class NotificationContentView extends FrameLayout implements Notification if (mExpandedRemoteInput != null) { mExpandedRemoteInput.onNotificationUpdateOrReset(); if (mExpandedRemoteInput.isActive()) { - mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent(); + if (mExpandedRemoteInputController != null) { + mPreviousExpandedRemoteInputIntent = + mExpandedRemoteInputController.getPendingIntent(); + } mCachedExpandedRemoteInput = mExpandedRemoteInput; mCachedExpandedRemoteInputViewController = mExpandedRemoteInputController; mExpandedRemoteInput.dispatchStartTemporaryDetach(); @@ -460,7 +463,10 @@ public class NotificationContentView extends FrameLayout implements Notification if (mHeadsUpRemoteInput != null) { mHeadsUpRemoteInput.onNotificationUpdateOrReset(); if (mHeadsUpRemoteInput.isActive()) { - mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent(); + if (mHeadsUpRemoteInputController != null) { + mPreviousHeadsUpRemoteInputIntent = + mHeadsUpRemoteInputController.getPendingIntent(); + } mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput; mCachedHeadsUpRemoteInputViewController = mHeadsUpRemoteInputController; mHeadsUpRemoteInput.dispatchStartTemporaryDetach(); @@ -961,14 +967,16 @@ public class NotificationContentView extends FrameLayout implements Notification private void transferRemoteInputFocus(int visibleType) { if (visibleType == VISIBLE_TYPE_HEADSUP - && mHeadsUpRemoteInput != null - && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) { - mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput); + && mHeadsUpRemoteInputController != null + && mExpandedRemoteInputController != null + && mExpandedRemoteInputController.isActive()) { + mHeadsUpRemoteInputController.stealFocusFrom(mExpandedRemoteInputController); } if (visibleType == VISIBLE_TYPE_EXPANDED - && mExpandedRemoteInput != null - && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) { - mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput); + && mExpandedRemoteInputController != null + && mHeadsUpRemoteInputController != null + && mHeadsUpRemoteInputController.isActive()) { + mExpandedRemoteInputController.stealFocusFrom(mHeadsUpRemoteInputController); } } @@ -1313,7 +1321,6 @@ public class NotificationContentView extends FrameLayout implements Notification // If we find a matching action in the new notification, focus, otherwise close. Notification.Action[] actions = entry.getSbn().getNotification().actions; if (existingPendingIntent != null) { - result.mView.setPendingIntent(existingPendingIntent); result.mController.setPendingIntent(existingPendingIntent); } if (result.mController.updatePendingIntentFromActions(actions)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 5b9dbd0f3361..27cc326fda19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -758,29 +758,30 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mDebugTextUsedYPositions.clear(); } int y = mTopPadding; - drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding"); + drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding = "+y); y = getLayoutHeight(); - drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight()"); + drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = "+y); y = (int) mMaxLayoutHeight; - drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight"); + drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = "+y); if (mKeyguardBottomPadding >= 0) { y = getHeight() - (int) mKeyguardBottomPadding; drawDebugInfo(canvas, y, Color.GRAY, - /* label= */ "getHeight() - mKeyguardBottomPadding"); + /* label= */ "getHeight() - mKeyguardBottomPadding = "+y); } y = getHeight() - getEmptyBottomMargin(); - drawDebugInfo(canvas, y, Color.GREEN, /* label= */ "getHeight() - getEmptyBottomMargin()"); + drawDebugInfo(canvas, y, Color.GREEN, + /* label= */ "getHeight() - getEmptyBottomMargin() = "+y); y = (int) (mAmbientState.getStackY()); - drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY()"); + drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = "+y); y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight()); drawDebugInfo(canvas, y, Color.BLUE, - /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight()"); + /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = "+y); } private void drawDebugInfo(Canvas canvas, int y, int color, String label) { @@ -1332,12 +1333,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ @ShadeViewRefactor(RefactorComponent.COORDINATOR) public void setExpandedHeight(float height) { - final float shadeBottom = getHeight() - getEmptyBottomMargin(); final boolean skipHeightUpdate = shouldSkipHeightUpdate(); - if (!skipHeightUpdate) { - final float expansionFraction = MathUtils.saturate(height / shadeBottom); - mAmbientState.setExpansionFraction(expansionFraction); - } updateStackPosition(); if (!skipHeightUpdate) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 952cd9ae69bc..e1f8c35c3755 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -202,12 +202,10 @@ public class StackScrollAlgorithm { float newHeight = state.height; float newNotificationEnd = newYTranslation + newHeight; boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned(); - final boolean shadeClosedWithHUN = - ambientState.isShadeOpening() && !ambientState.isShadeExpanded(); if (mClipNotificationScrollToTop && (!state.inShelf || (isHeadsUp && !firstHeadsUp)) && newYTranslation < clipStart - && shadeClosedWithHUN) { + && !ambientState.isShadeExpanded()) { // The previous view is overlapping on top, clip! float overlapAmount = clipStart - newYTranslation; state.clipTopAmount = (int) overlapAmount; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index a7f950eaf167..ec2d608b2683 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -2881,8 +2881,7 @@ public class CentralSurfaces extends CoreStartable implements } boolean updateIsKeyguard(boolean forceStateChange) { - boolean wakeAndUnlocking = mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; + boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock(); // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise // there's no surface we can show to the user. Note that the device goes fully interactive @@ -2892,7 +2891,7 @@ public class CentralSurfaces extends CoreStartable implements && (!mDeviceInteractive || (isGoingToSleep() && (isScreenFullyOff() || (mKeyguardStateController.isShowing() && !isOccluded())))); - boolean isWakingAndOccluded = isOccluded() && isWaking(); + boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake(); boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested() || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded; if (keyguardForDozing) { @@ -3076,7 +3075,6 @@ public class CentralSurfaces extends CoreStartable implements mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); releaseGestureWakeLock(); mNotificationPanelViewController.onAffordanceLaunchEnded(); - mNotificationPanelViewController.cancelAnimation(); mNotificationPanelViewController.resetAlpha(); mNotificationPanelViewController.resetTranslation(); mNotificationPanelViewController.resetViewGroupFade(); @@ -3702,8 +3700,9 @@ public class CentralSurfaces extends CoreStartable implements == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; } - boolean isWaking() { - return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING; + boolean isWakingOrAwake() { + return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING + || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE; } public void notifyBiometricAuthModeChanged() { 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/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 0a2ea4cfe11a..1891ab017ef8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -616,6 +616,11 @@ public class NotificationPanelViewController extends PanelViewController { */ private float mKeyguardOnlyContentAlpha = 1.0f; + /** + * The translationY of the views which only show on the keyguard but in shade / shade locked. + */ + private int mKeyguardOnlyTransitionTranslationY = 0; + private float mUdfpsMaxYBurnInOffset; /** @@ -1575,6 +1580,8 @@ public class NotificationPanelViewController extends PanelViewController { private void updateClock() { float alpha = mClockPositionResult.clockAlpha * mKeyguardOnlyContentAlpha; mKeyguardStatusViewController.setAlpha(alpha); + mKeyguardStatusViewController + .setTranslationYExcludingMedia(mKeyguardOnlyTransitionTranslationY); if (mKeyguardQsUserSwitchController != null) { mKeyguardQsUserSwitchController.setAlpha(alpha); } @@ -2732,11 +2739,12 @@ public class NotificationPanelViewController extends PanelViewController { } /** - * Set the alpha of the keyguard elements which only show on the lockscreen, but not in - * shade locked / shade. This is used when dragging down to the full shade. + * Set the alpha and translationY of the keyguard elements which only show on the lockscreen, + * but not in shade locked / shade. This is used when dragging down to the full shade. */ - public void setKeyguardOnlyContentAlpha(float keyguardAlpha) { + public void setKeyguardTransitionProgress(float keyguardAlpha, int keyguardTranslationY) { mKeyguardOnlyContentAlpha = Interpolators.ALPHA_IN.getInterpolation(keyguardAlpha); + mKeyguardOnlyTransitionTranslationY = keyguardTranslationY; if (mBarState == KEYGUARD) { // If the animator is running, it's already fading out the content and this is a reset mBottomAreaShadeAlpha = mKeyguardOnlyContentAlpha; @@ -3001,9 +3009,7 @@ public class NotificationPanelViewController extends PanelViewController { } private int calculatePanelHeightShade() { - int emptyBottomMargin = mNotificationStackScrollLayoutController.getEmptyBottomMargin(); - int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin; - + final int maxHeight = mNotificationStackScrollLayoutController.getHeight(); if (mBarState == KEYGUARD) { int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight() + mNotificationStackScrollLayoutController.getIntrinsicContentHeight(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index 0ff010aedfff..16e573280417 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -386,10 +386,12 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } visible = true; } - if (visible) { - mNotificationShadeView.setVisibility(View.VISIBLE); - } else { - mNotificationShadeView.setVisibility(View.INVISIBLE); + if (mNotificationShadeView != null) { + if (visible) { + mNotificationShadeView.setVisibility(View.VISIBLE); + } else { + mNotificationShadeView.setVisibility(View.INVISIBLE); + } } } 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/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 1d560c4592a6..24f5ff86a794 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -382,7 +382,7 @@ public abstract class PanelViewController { protected void startExpandMotion(float newX, float newY, boolean startTracking, float expandedHeight) { - if (!mHandlingPointerUp) { + if (!mHandlingPointerUp && !mStatusBarStateController.isDozing()) { beginJankMonitoring(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); } mInitialOffsetOnTouch = expandedHeight; @@ -654,7 +654,9 @@ public abstract class PanelViewController { @Override public void onAnimationStart(Animator animation) { - beginJankMonitoring(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); + if (!mStatusBarStateController.isDozing()) { + beginJankMonitoring(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); + } } @Override @@ -794,6 +796,7 @@ public abstract class PanelViewController { } mExpandedFraction = Math.min(1f, maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); + mAmbientState.setExpansionFraction(mExpandedFraction); onHeightUpdated(mExpandedHeight); updatePanelExpansionAndVisibility(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 108d98a129b2..637e4bee8948 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -370,6 +370,8 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte mLogger.logExpandingBubble(notificationKey); removeHunAfterClick(row); expandBubbleStackOnMainThread(entry); + mMainThreadHandler.post( + () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry)); } else { startNotificationIntent(intent, fillInIntent, entry, row, animate, isActivityIntent); } @@ -395,7 +397,6 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte mMainThreadHandler.post(() -> { final Runnable removeNotification = () -> { mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK, summaryToRemove); - mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry); }; if (mPresenter.isCollapsing()) { // To avoid lags we're only performing the remove @@ -405,9 +406,6 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte removeNotification.run(); } }); - } else { - mMainThreadHandler.post( - () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry)); } mIsCollapsingToShowActivityOverLockscreen = false; @@ -483,14 +481,19 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte boolean isActivityIntent) { mLogger.logStartNotificationIntent(entry.getKey(), intent); try { + Runnable onFinishAnimationCallback = + () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry); ActivityLaunchAnimator.Controller animationController = new StatusBarLaunchAnimatorController( - mNotificationAnimationProvider.getAnimatorController(row), + mNotificationAnimationProvider + .getAnimatorController(row, onFinishAnimationCallback), mCentralSurfaces, isActivityIntent); - - mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController, - animate, intent.getCreatorPackage(), (adapter) -> { + mActivityLaunchAnimator.startPendingIntentWithAnimation( + animationController, + animate, + intent.getCreatorPackage(), + (adapter) -> { long eventTime = row.getAndResetLastActionUpTime(); Bundle options = eventTime > 0 ? getActivityOptions( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 48949f92413d..4d6d05f2b628 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -22,8 +22,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.ActivityManager; import android.app.Notification; -import android.app.PendingIntent; -import android.app.RemoteInput; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; @@ -75,7 +73,6 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.phone.LightBarController; @@ -111,21 +108,15 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private ProgressBar mProgressBar; private ImageView mDelete; private ImageView mDeleteBg; - // TODO(b/193539698): remove reveal param fields, turn them into parameters where needed - private int mRevealCx; - private int mRevealCy; - private int mRevealR; private boolean mColorized; private int mTint; private boolean mResetting; + @Nullable private RevealParams mRevealParams; // TODO(b/193539698): move these to a Controller private RemoteInputController mController; private final UiEventLogger mUiEventLogger; private NotificationEntry mEntry; - private PendingIntent mPendingIntent; - private RemoteInput mRemoteInput; - private RemoteInput[] mRemoteInputs; private boolean mRemoved; private NotificationViewWrapper mWrapper; @@ -397,9 +388,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene // During removal, we get reattached and lose focus. Not hiding in that // case to prevent flicker. if (!mRemoved) { - if (animate && mRevealR > 0) { - Animator reveal = ViewAnimationUtils.createCircularReveal( - this, mRevealCx, mRevealCy, mRevealR, 0); + if (animate && mRevealParams != null && mRevealParams.radius > 0) { + Animator reveal = mRevealParams.createCircularHideAnimator(this); reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT); reveal.addListener(new AnimatorListenerAdapter() { @@ -454,30 +444,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mController.removeSpinning(mEntry.getKey(), mToken); } - public void setPendingIntent(PendingIntent pendingIntent) { - mPendingIntent = pendingIntent; + public void setHintText(CharSequence hintText) { + mEditText.setHint(hintText); } - /** - * Sets the remote input for this view. - * - * @param remoteInputs The remote inputs that need to be sent to the app. - * @param remoteInput The remote input that needs to be activated. - * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or - * {@code null} if the user is not editing a smart reply. - */ - public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput, - @Nullable EditedSuggestionInfo editedSuggestionInfo) { - mRemoteInputs = remoteInputs; - mRemoteInput = remoteInput; - mEditText.setHint(mRemoteInput.getLabel()); - mEditText.setSupportedMimeTypes(remoteInput.getAllowedDataTypes()); - - mEntry.editedSuggestionInfo = editedSuggestionInfo; - if (editedSuggestionInfo != null) { - mEntry.remoteInputText = editedSuggestionInfo.originalText; - mEntry.remoteInputAttachment = null; - } + public void setSupportedMimeTypes(Collection<String> mimeTypes) { + mEditText.setSupportedMimeTypes(mimeTypes); } /** Populates the text field of the remote input with the given content. */ @@ -486,9 +458,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } public void focusAnimated() { - if (getVisibility() != VISIBLE) { - Animator animator = ViewAnimationUtils.createCircularReveal( - this, mRevealCx, mRevealCy, 0, mRevealR); + if (getVisibility() != VISIBLE && mRevealParams != null) { + Animator animator = mRevealParams.createCircularRevealAnimator(this); animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); animator.start(); @@ -587,30 +558,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return mEditText.isFocused() && mEditText.isEnabled(); } - // TODO(b/193539698): move this to the controller - public void stealFocusFrom(RemoteInputView other) { - other.close(); - setPendingIntent(other.mPendingIntent); - setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo); - setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR); - getController().setPendingIntent(other.mPendingIntent); - getController().setRemoteInput(other.mRemoteInput); - getController().setRemoteInputs(other.mRemoteInputs); - focus(); - } - - public PendingIntent getPendingIntent() { - return mPendingIntent; - } - public void setRemoved() { mRemoved = true; } - public void setRevealParameters(int cx, int cy, int r) { - mRevealCx = cx; - mRevealCy = cy; - mRevealR = r; + public void setRevealParameters(@Nullable RevealParams revealParams) { + mRevealParams = revealParams; } @Override @@ -938,4 +891,24 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } } + + public static class RevealParams { + final int centerX; + final int centerY; + final int radius; + + public RevealParams(int centerX, int centerY, int radius) { + this.centerX = centerX; + this.centerY = centerY; + this.radius = radius; + } + + Animator createCircularRevealAnimator(View view) { + return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0); + } + + Animator createCircularHideAnimator(View view) { + return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt index ef0a5b4235c7..bd878750dfe1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt @@ -33,7 +33,9 @@ import com.android.systemui.R import com.android.systemui.statusbar.NotificationRemoteInputManager import com.android.systemui.statusbar.RemoteInputController import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo import com.android.systemui.statusbar.policy.RemoteInputView.NotificationRemoteInputEvent +import com.android.systemui.statusbar.policy.RemoteInputView.RevealParams import com.android.systemui.statusbar.policy.dagger.RemoteInputViewScope import javax.inject.Inject @@ -41,6 +43,8 @@ interface RemoteInputViewController { fun bind() fun unbind() + val isActive: Boolean + /** * A [NotificationRemoteInputManager.BouncerChecker] that will be used to determine if the * device needs to be unlocked before sending the RemoteInput. @@ -55,6 +59,14 @@ interface RemoteInputViewController { /** Other [RemoteInput]s from the notification associated with this Controller. */ var remoteInputs: Array<RemoteInput>? + var revealParams: RevealParams? + + /** + * Sets the smart reply that should be inserted in the remote input, or `null` if the user is + * not editing a smart reply. + */ + fun setEditedSuggestionInfo(info: EditedSuggestionInfo?) + /** * Tries to find an action in {@param actions} that matches the current pending intent * of this view and updates its state to that of the found action @@ -68,6 +80,19 @@ interface RemoteInputViewController { /** Unregisters a listener previously registered via [addOnSendRemoteInputListener] */ fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener) + + fun close() + + fun focus() + + fun stealFocusFrom(other: RemoteInputViewController) { + other.close() + remoteInput = other.remoteInput + remoteInputs = other.remoteInputs + revealParams = other.revealParams + pendingIntent = other.pendingIntent + focus() + } } /** Listener for send events */ @@ -100,15 +125,41 @@ class RemoteInputViewControllerImpl @Inject constructor( private var isBound = false - override var pendingIntent: PendingIntent? = null override var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? = null + override var remoteInput: RemoteInput? = null + set(value) { + field = value + value?.takeIf { isBound }?.let { + view.setHintText(it.label) + view.setSupportedMimeTypes(it.allowedDataTypes) + } + } + + override var pendingIntent: PendingIntent? = null override var remoteInputs: Array<RemoteInput>? = null + override var revealParams: RevealParams? = null + set(value) { + field = value + if (isBound) { + view.setRevealParameters(value) + } + } + + override val isActive: Boolean get() = view.isActive + override fun bind() { if (isBound) return isBound = true + // TODO: refreshUI method? + remoteInput?.let { + view.setHintText(it.label) + view.setSupportedMimeTypes(it.allowedDataTypes) + } + view.setRevealParameters(revealParams) + view.addOnEditTextFocusChangedListener(onFocusChangeListener) view.addOnSendRemoteInputListener(onSendRemoteInputListener) } @@ -121,6 +172,14 @@ class RemoteInputViewControllerImpl @Inject constructor( view.removeOnSendRemoteInputListener(onSendRemoteInputListener) } + override fun setEditedSuggestionInfo(info: EditedSuggestionInfo?) { + entry.editedSuggestionInfo = info + if (info != null) { + entry.remoteInputText = info.originalText + entry.remoteInputAttachment = null + } + } + override fun updatePendingIntentFromActions(actions: Array<Notification.Action>?): Boolean { actions ?: return false val current: Intent = pendingIntent?.intent ?: return false @@ -132,8 +191,7 @@ class RemoteInputViewControllerImpl @Inject constructor( pendingIntent = actionIntent remoteInput = input remoteInputs = inputs - view.pendingIntent = actionIntent - view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */) + setEditedSuggestionInfo(null) return true } return false @@ -148,6 +206,14 @@ class RemoteInputViewControllerImpl @Inject constructor( onSendListeners.remove(listener) } + override fun close() { + view.close() + } + + override fun focus() { + view.focus() + } + private val onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus -> remoteInputQuickSettingsDisabler.setRemoteInputActive(hasFocus) } @@ -217,11 +283,12 @@ class RemoteInputViewControllerImpl @Inject constructor( * @return returns intent with granted URI permissions that should be used immediately */ private fun prepareRemoteInput(remoteInput: RemoteInput): Intent = - if (entry.remoteInputAttachment == null) prepareRemoteInputFromText(remoteInput) - else prepareRemoteInputFromData( - remoteInput, - entry.remoteInputMimeType, - entry.remoteInputUri) + if (entry.remoteInputAttachment == null) + prepareRemoteInputFromText(remoteInput) + else prepareRemoteInputFromData( + remoteInput, + entry.remoteInputMimeType, + entry.remoteInputUri) private fun prepareRemoteInputFromText(remoteInput: RemoteInput): Intent { val results = Bundle() @@ -232,11 +299,10 @@ class RemoteInputViewControllerImpl @Inject constructor( view.clearAttachment() entry.remoteInputUri = null entry.remoteInputMimeType = null - if (entry.editedSuggestionInfo == null) { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT) - } else { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE) - } + val resultSource = entry.editedSuggestionInfo + ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT } + ?: RemoteInput.SOURCE_CHOICE + RemoteInput.setResultsSource(fillInIntent, resultSource) return fillInIntent } @@ -266,11 +332,10 @@ class RemoteInputViewControllerImpl @Inject constructor( entry.remoteInputText = fullText // mirror prepareRemoteInputFromText for text input - if (entry.editedSuggestionInfo == null) { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT) - } else if (entry.remoteInputAttachment == null) { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE) - } + val resultSource = entry.editedSuggestionInfo + ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT } + ?: RemoteInput.SOURCE_CHOICE + RemoteInput.setResultsSource(fillInIntent, resultSource) return fillInIntent } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt index e980eb783d79..8e1e42a9c9a2 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt @@ -88,6 +88,6 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() { fun onPause_clearsTextField() { mKeyguardPatternViewController.init() mKeyguardPatternViewController.onPause() - verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern) + verify(mKeyguardMessageAreaController).setMessage("") } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java index 2fc912288623..1753157c631d 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java @@ -112,4 +112,13 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase { mKeyguardUpdateMonitorCallbackCaptor.getValue().onUserSwitchComplete(0); verify(mKeyguardClockSwitchController).refreshFormat(); } + + @Test + public void setTranslationYExcludingMedia_forwardsCallToView() { + float translationY = 123f; + + mController.setTranslationYExcludingMedia(translationY); + + verify(mKeyguardStatusView).setChildrenTranslationYExcludingMediaView(translationY); + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt new file mode 100644 index 000000000000..ce44f4d82d69 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt @@ -0,0 +1,55 @@ +package com.android.keyguard + +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.children +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@RunWithLooper(setAsMainLooper = true) +class KeyguardStatusViewTest : SysuiTestCase() { + + private lateinit var keyguardStatusView: KeyguardStatusView + private val mediaView: View + get() = keyguardStatusView.findViewById(R.id.status_view_media_container) + private val statusViewContainer: ViewGroup + get() = keyguardStatusView.findViewById(R.id.status_view_container) + private val childrenExcludingMedia + get() = statusViewContainer.children.filter { it != mediaView } + + @Before + fun setUp() { + keyguardStatusView = LayoutInflater.from(context) + .inflate(R.layout.keyguard_status_view, /* root= */ null) as KeyguardStatusView + } + + @Test + fun setChildrenTranslationYExcludingMediaView_mediaViewIsNotTranslated() { + val translationY = 1234f + + keyguardStatusView.setChildrenTranslationYExcludingMediaView(translationY) + + assertThat(mediaView.translationY).isEqualTo(0) + } + + @Test + fun setChildrenTranslationYExcludingMediaView_childrenAreTranslated() { + val translationY = 1234f + + keyguardStatusView.setChildrenTranslationYExcludingMediaView(translationY) + + childrenExcludingMedia.forEach { + assertThat(it.translationY).isEqualTo(translationY) + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index a49c4d76445b..c684b66d2892 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -172,11 +172,10 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnification_notifySourceBoundsChanged() { - mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, - Float.NaN, /* magnificationFrameOffsetRatioX= */ 0, - /* magnificationFrameOffsetRatioY= */ 0, null); - }); + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, + Float.NaN, /* magnificationFrameOffsetRatioX= */ 0, + /* magnificationFrameOffsetRatioY= */ 0, null)); // Waits for the surface created verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS)).onSourceBoundsChanged( @@ -184,6 +183,16 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @Test + public void enableWindowMagnification_disabled_notifySourceBoundsChanged() { + enableWindowMagnification_notifySourceBoundsChanged(); + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationController.deleteWindowMagnification(null)); + Mockito.reset(mWindowMagnifierCallback); + + enableWindowMagnification_notifySourceBoundsChanged(); + } + + @Test public void enableWindowMagnification_withAnimation_schedulesFrame() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(2.0f, 10, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 1856fda14e1b..613931f1341f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -48,6 +48,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; @@ -64,8 +65,8 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.VibratorHelper; -import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.SystemUIDialogManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; @@ -188,6 +189,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor; private IUdfpsOverlayController mOverlayController; @Captor private ArgumentCaptor<UdfpsView.OnTouchListener> mTouchListenerCaptor; + @Captor private ArgumentCaptor<View.OnHoverListener> mHoverListenerCaptor; @Captor private ArgumentCaptor<Runnable> mOnIlluminatedRunnableCaptor; @Captor private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor; private ScreenLifecycle.Observer mScreenObserver; @@ -568,23 +570,24 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test - public void playHapticOnTouchUdfpsArea() throws RemoteException { + public void playHapticOnTouchUdfpsArea_a11yTouchExplorationEnabled() throws RemoteException { // Configure UdfpsView to accept the ACTION_DOWN event when(mUdfpsView.isIlluminationRequested()).thenReturn(false); when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); - // GIVEN that the overlay is showing + // GIVEN that the overlay is showing and a11y touch exploration enabled + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); - // WHEN ACTION_DOWN is received - verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); - MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); - mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - downEvent.recycle(); - MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); - mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + // WHEN ACTION_HOVER is received + verify(mUdfpsView).setOnHoverListener(mHoverListenerCaptor.capture()); + MotionEvent enterEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0); + mHoverListenerCaptor.getValue().onHover(mUdfpsView, enterEvent); + enterEvent.recycle(); + MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0); + mHoverListenerCaptor.getValue().onHover(mUdfpsView, moveEvent); moveEvent.recycle(); // THEN tick haptic is played @@ -600,4 +603,34 @@ public class UdfpsControllerTest extends SysuiTestCase { assertEquals(VibrationAttributes.USAGE_COMMUNICATION_REQUEST, UdfpsController.VIBRATION_ATTRIBUTES.getUsage()); } + + @Test + public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled() throws RemoteException { + // Configure UdfpsView to accept the ACTION_DOWN event + when(mUdfpsView.isIlluminationRequested()).thenReturn(false); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + + // GIVEN that the overlay is showing and a11y touch exploration NOT enabled + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + // WHEN ACTION_DOWN is received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + downEvent.recycle(); + MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + moveEvent.recycle(); + + // THEN NO haptic played + verify(mVibrator, never()).vibrate( + anyInt(), + anyString(), + any(), + anyString(), + any()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index badafa4cf5e5..f4b378e6c19c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -27,6 +27,7 @@ import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE; import static com.android.systemui.doze.DozeMachine.State.FINISH; import static com.android.systemui.doze.DozeMachine.State.INITIALIZED; import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotSame; @@ -468,37 +469,39 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); - when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.transitionTo(INITIALIZED, DOZE); // If we're dozing after a timeout, and playing the unlocked screen animation, we should // stay at or below dim brightness, because the screen dims just before timeout. assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); + + // Once we transition to Doze, use the doze brightness + mScreen.transitionTo(INITIALIZED, DOZE); + assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); } @Test public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); - when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.transitionTo(INITIALIZED, DOZE); // If we're playing the unlocked screen off animation after a power button press, we should // leave the brightness alone. assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + + mScreen.transitionTo(INITIALIZED, DOZE); + assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); } @Test public void transitionToDoze_noClampBrightness_afterTimeout_noScreenOff_doesNotClampToDim() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); - when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); @@ -514,11 +517,9 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mWakefulnessLifecycle.getWakefulness()).thenReturn( WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); - when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.transitionTo(INITIALIZED, DOZE); assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); } @@ -529,7 +530,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); when(mWakefulnessLifecycle.getWakefulness()).thenReturn( WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); - when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); 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/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt index dcbe0ab96dac..daf81bdc6e82 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt @@ -37,7 +37,6 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations import javax.inject.Provider -import org.mockito.Mockito.`when` as whenever private val DATA = MediaData( userId = -1, @@ -83,7 +82,6 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) mediaCarouselController = MediaCarouselController( context, mediaControlPanelFactory, 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 cb68d81287df..90eff1ae9804 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -101,7 +101,6 @@ public class MediaControlPanelTest : SysuiTestCase() { @Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory @Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var falsingManager: FalsingManager - @Mock private lateinit var mediaFlags: MediaFlags private lateinit var appIcon: ImageView private lateinit var albumView: ImageView private lateinit var titleText: TextView @@ -147,7 +146,7 @@ public class MediaControlPanelTest : SysuiTestCase() { player = MediaControlPanel(context, bgExecutor, activityStarter, broadcastSender, mediaViewController, seekBarViewModel, Lazy { mediaDataManager }, - mediaOutputDialogFactory, mediaCarouselController, falsingManager, mediaFlags, clock) + mediaOutputDialogFactory, mediaCarouselController, falsingManager, clock) whenever(seekBarViewModel.progress).thenReturn(seekBarData) // Set up mock views for the players @@ -215,9 +214,6 @@ public class MediaControlPanelTest : SysuiTestCase() { device = device, active = true, resumeAction = null) - - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) - whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } /** @@ -295,9 +291,6 @@ public class MediaControlPanelTest : SysuiTestCase() { @Test fun bindSemanticActionsOldLayout() { - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) - whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) - val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), @@ -332,9 +325,6 @@ public class MediaControlPanelTest : SysuiTestCase() { @Test fun bindSemanticActionsNewLayout() { - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) - whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) - val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), @@ -381,9 +371,6 @@ public class MediaControlPanelTest : SysuiTestCase() { @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"), 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 925ae30e8773..be2450d11c08 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.tuner.TunerService import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock @@ -37,6 +38,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito @@ -167,7 +169,7 @@ class MediaDataManagerTest : SysuiTestCase() { whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA) whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf(mediaRecommendationItem)) whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L) - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(false) } @After @@ -594,7 +596,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_noState_usesNotification() { val desc = "Notification Action" - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) whenever(controller.playbackState).thenReturn(null) val notifWithAction = SbnBuilder().run { @@ -621,7 +623,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_hasPrevNext() { val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4") - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) val stateActions = PlaybackState.ACTION_PLAY or PlaybackState.ACTION_SKIP_TO_PREVIOUS or PlaybackState.ACTION_SKIP_TO_NEXT @@ -669,7 +671,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_noPrevNext_usesCustom() { val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5") - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) val stateActions = PlaybackState.ACTION_PLAY val stateBuilder = PlaybackState.Builder() .setActions(stateActions) @@ -707,7 +709,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_reservedSpace() { val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4") - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) val stateActions = PlaybackState.ACTION_PLAY val stateBuilder = PlaybackState.Builder() .setActions(stateActions) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt index b359ae5317b1..8e201b5a3e87 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt @@ -117,9 +117,9 @@ class MediaHierarchyManagerTest : SysuiTestCase() { dreamOverlayStateController) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) - setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN) - setupHost(qsHost, MediaHierarchyManager.LOCATION_QS) - setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS) + setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP) + setupHost(qsHost, MediaHierarchyManager.LOCATION_QS, QS_TOP) + setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS, QQS_TOP) `when`(statusBarStateController.state).thenReturn(StatusBarState.SHADE) `when`(mediaCarouselController.mediaCarouselScrollHandler) .thenReturn(mediaCarouselScrollHandler) @@ -130,9 +130,9 @@ class MediaHierarchyManagerTest : SysuiTestCase() { clearInvocations(mediaCarouselController) } - private fun setupHost(host: MediaHost, location: Int) { + private fun setupHost(host: MediaHost, location: Int, top: Int) { `when`(host.location).thenReturn(location) - `when`(host.currentBounds).thenReturn(Rect()) + `when`(host.currentBounds).thenReturn(Rect(0, top, 0, top)) `when`(host.hostView).thenReturn(uniqueObjectHostView) `when`(host.visible).thenReturn(true) mediaHiearchyManager.register(host) @@ -257,6 +257,20 @@ class MediaHierarchyManagerTest : SysuiTestCase() { verify(mediaCarouselController).closeGuts() } + @Test + fun getGuidedTransformationTranslationY_notInGuidedTransformation_returnsNegativeNumber() { + assertThat(mediaHiearchyManager.getGuidedTransformationTranslationY()).isLessThan(0) + } + + @Test + fun getGuidedTransformationTranslationY_inGuidedTransformation_returnsCurrentTranslation() { + enterGuidedTransformation() + + val expectedTranslation = LOCKSCREEN_TOP - QS_TOP + assertThat(mediaHiearchyManager.getGuidedTransformationTranslationY()) + .isEqualTo(expectedTranslation) + } + private fun enableSplitShade() { context.getOrCreateTestableResources().addOverride( R.bool.config_use_split_notification_shade, true @@ -284,4 +298,16 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private fun expandQS() { mediaHiearchyManager.qsExpansion = 1.0f } + + private fun enterGuidedTransformation() { + mediaHiearchyManager.qsExpansion = 1.0f + goToLockscreen() + mediaHiearchyManager.setTransitionToFullShadeAmount(123f) + } + + companion object { + private const val QQS_TOP = 123 + private const val QS_TOP = 456 + private const val LOCKSCREEN_TOP = 789 + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt new file mode 100644 index 000000000000..b7d5ba170e6d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt @@ -0,0 +1,55 @@ +package com.android.systemui.media + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.animation.MeasurementInput +import com.android.systemui.util.animation.TransitionLayout +import com.android.systemui.util.animation.TransitionViewState +import junit.framework.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Tests for {@link MediaViewController}. + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class MediaViewControllerTest : SysuiTestCase() { + private val configurationController = + com.android.systemui.statusbar.phone.ConfigurationControllerImpl(context) + private val mediaHostStatesManager = MediaHostStatesManager() + private val mediaViewController = + MediaViewController(context, configurationController, mediaHostStatesManager) + private val mediaHostStateHolder = MediaHost.MediaHostStateHolder() + private var transitionLayout = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0) + + @Before + fun setUp() { + mediaViewController.attach(transitionLayout, MediaViewController.TYPE.PLAYER) + } + + @Test + fun testObtainViewState_applySquishFraction_toTransitionViewState_height() { + transitionLayout.measureState = TransitionViewState().apply { + this.height = 100 + } + mediaHostStateHolder.expansion = 1f + val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY) + val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY) + mediaHostStateHolder.measurementInput = + MeasurementInput(widthMeasureSpec, heightMeasureSpec) + + // Test no squish + mediaHostStateHolder.squishFraction = 1f + assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100) + + // Test half squish + mediaHostStateHolder.squishFraction = 0.5f + assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50) + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java index 19a9863f6f5e..6b7e5b9335f2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java @@ -20,21 +20,18 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Intent; -import android.content.IntentFilter; import android.os.Handler; -import android.os.Looper; +import android.os.RemoteException; import android.os.UserHandle; -import android.service.quicksettings.TileService; +import android.service.quicksettings.IQSTileService; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -49,6 +46,7 @@ import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSFactoryImpl; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoTileManager; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -68,17 +66,25 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Optional; +import javax.inject.Provider; + @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper public class TileServicesTest extends SysuiTestCase { private static int NUM_FAKES = TileServices.DEFAULT_MAX_BOUND * 2; + private static final ComponentName TEST_COMPONENT = + ComponentName.unflattenFromString("pkg/.cls"); + private TileServices mTileService; + private TestableLooper mTestableLooper; private ArrayList<TileServiceManager> mManagers; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock + private CommandQueue mCommandQueue; + @Mock private StatusBarIconController mStatusBarIconController; @Mock private QSFactoryImpl mQSFactory; @@ -116,17 +122,20 @@ public class TileServicesTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mDependency.injectMockDependency(BluetoothController.class); mManagers = new ArrayList<>(); + mTestableLooper = TestableLooper.get(this); when(mTileServiceRequestControllerBuilder.create(any())) .thenReturn(mTileServiceRequestController); when(mTileLifecycleManagerFactory.create(any(Intent.class), any(UserHandle.class))) .thenReturn(mTileLifecycleManager); + Provider<Handler> provider = () -> new Handler(mTestableLooper.getLooper()); + QSTileHost host = new QSTileHost(mContext, mStatusBarIconController, mQSFactory, - new Handler(), - Looper.myLooper(), + provider.get(), + mTestableLooper.getLooper(), mPluginManager, mTunerService, () -> mAutoTileManager, @@ -140,8 +149,8 @@ public class TileServicesTest extends SysuiTestCase { mock(CustomTileStatePersister.class), mTileServiceRequestControllerBuilder, mTileLifecycleManagerFactory); - mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher, - mUserTracker, mKeyguardStateController); + mTileService = new TestTileServices(host, provider, mBroadcastDispatcher, + mUserTracker, mKeyguardStateController, mCommandQueue); } @After @@ -152,24 +161,6 @@ public class TileServicesTest extends SysuiTestCase { } @Test - public void testActiveTileListenerRegisteredOnAllUsers() { - ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class); - verify(mBroadcastDispatcher).registerReceiver(any(), captor.capture(), any(), eq( - UserHandle.ALL)); - assertTrue(captor.getValue().hasAction(TileService.ACTION_REQUEST_LISTENING)); - } - - @Test - public void testBadComponentName_doesntCrash() { - ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mBroadcastDispatcher).registerReceiver(captor.capture(), any(), any(), eq( - UserHandle.ALL)); - Intent intent = new Intent(TileService.ACTION_REQUEST_LISTENING) - .putExtra(Intent.EXTRA_COMPONENT_NAME, "abc"); - captor.getValue().onReceive(mContext, intent); - } - - @Test public void testRecalculateBindAllowance() { // Add some fake tiles. for (int i = 0; i < NUM_FAKES; i++) { @@ -225,11 +216,36 @@ public class TileServicesTest extends SysuiTestCase { } } + @Test + public void testRegisterCommand() { + verify(mCommandQueue).addCallback(any()); + } + + @Test + public void testRequestListeningStatusCommand() throws RemoteException { + ArgumentCaptor<CommandQueue.Callbacks> captor = + ArgumentCaptor.forClass(CommandQueue.Callbacks.class); + verify(mCommandQueue).addCallback(captor.capture()); + + CustomTile mockTile = mock(CustomTile.class); + when(mockTile.getComponent()).thenReturn(TEST_COMPONENT); + + TileServiceManager manager = mTileService.getTileWrapper(mockTile); + when(manager.isActiveTile()).thenReturn(true); + when(manager.getTileService()).thenReturn(mock(IQSTileService.class)); + + captor.getValue().requestTileServiceListeningState(TEST_COMPONENT); + mTestableLooper.processAllMessages(); + verify(manager).setBindRequested(true); + verify(manager.getTileService()).onStartListening(); + } + private class TestTileServices extends TileServices { - TestTileServices(QSTileHost host, Looper looper, + TestTileServices(QSTileHost host, Provider<Handler> handlerProvider, BroadcastDispatcher broadcastDispatcher, UserTracker userTracker, - KeyguardStateController keyguardStateController) { - super(host, looper, broadcastDispatcher, userTracker, keyguardStateController); + KeyguardStateController keyguardStateController, CommandQueue commandQueue) { + super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController, + commandQueue); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java index 8297850d21a1..b652aee0f6aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java @@ -104,8 +104,6 @@ public class QRCodeScannerTileTest extends SysuiTestCase { assertEquals(state.label, mContext.getString(R.string.qr_code_scanner_title)); assertEquals(state.contentDescription, mContext.getString(R.string.qr_code_scanner_title)); assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.ic_qr_code_scanner)); - assertEquals(state.secondaryLabel, - mContext.getString(R.string.qr_code_scanner_description)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index 3c1a73eb672e..ad643fed969b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -226,6 +226,10 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { @After public void tearDown() throws Exception { mTextView.setAnimationsEnabled(true); + if (mController != null) { + mController.destroy(); + mController = null; + } } private void createController() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index 067caa98102b..64a0a2342a44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -44,6 +44,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever +import org.mockito.ArgumentMatchers.eq private fun <T> anyObject(): T { return Mockito.anyObject<T>() @@ -260,6 +261,49 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { } @Test + fun setDragAmount_setsKeyguardTransitionProgress() { + transitionController.dragDownAmount = 10f + + verify(notificationPanelController).setKeyguardTransitionProgress(anyFloat(), anyInt()) + } + + @Test + fun setDragAmount_setsKeyguardAlphaBasedOnDistance() { + val alphaDistance = context.resources.getDimensionPixelSize( + R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance) + transitionController.dragDownAmount = 10f + + val expectedAlpha = 1 - 10f / alphaDistance + verify(notificationPanelController) + .setKeyguardTransitionProgress(eq(expectedAlpha), anyInt()) + } + + @Test + fun setDragAmount_notInSplitShade_setsKeyguardTranslationToZero() { + val mediaTranslationY = 123 + disableSplitShade() + whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()) + .thenReturn(mediaTranslationY) + + transitionController.dragDownAmount = 10f + + verify(notificationPanelController).setKeyguardTransitionProgress(anyFloat(), eq(0)) + } + + @Test + fun setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslation() { + val mediaTranslationY = 123 + enableSplitShade() + whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()) + .thenReturn(mediaTranslationY) + + transitionController.dragDownAmount = 10f + + verify(notificationPanelController) + .setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY)) + } + + @Test fun setDragDownAmount_setsValueOnMediaHierarchyManager() { transitionController.dragDownAmount = 10f @@ -276,8 +320,16 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { } private fun enableSplitShade() { + setSplitShadeEnabled(true) + } + + private fun disableSplitShade() { + setSplitShadeEnabled(false) + } + + private fun setSplitShadeEnabled(enabled: Boolean) { context.getOrCreateTestableResources().addOverride( - R.bool.config_use_split_notification_shade, true + R.bool.config_use_split_notification_shade, enabled ) configurationController.notifyConfigurationChanged() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt index 3a60c049b3f3..9f82a5673c6e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt @@ -31,6 +31,7 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { @Mock lateinit var notificationListContainer: NotificationListContainer @Mock lateinit var headsUpManager: HeadsUpManagerPhone @Mock lateinit var jankMonitor: InteractionJankMonitor + @Mock lateinit var onFinishAnimationCallback: Runnable private lateinit var notificationTestHelper: NotificationTestHelper private lateinit var notification: ExpandableNotificationRow @@ -52,7 +53,8 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { notificationListContainer, headsUpManager, notification, - jankMonitor + jankMonitor, + onFinishAnimationCallback ) } @@ -61,7 +63,7 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { } @Test - fun testHunIsRemovedIfWeDontAnimateLaunch() { + fun testHunIsRemovedAndCallbackIsInvokedIfWeDontAnimateLaunch() { flagNotificationAsHun() controller.onIntentStarted(willAnimate = false) @@ -69,10 +71,11 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { assertFalse(notification.entry.isExpandAnimationRunning) verify(headsUpManager).removeNotification( notificationKey, true /* releaseImmediately */, true /* animate */) + verify(onFinishAnimationCallback).run() } @Test - fun testHunIsRemovedWhenAnimationIsCancelled() { + fun testHunIsRemovedAndCallbackIsInvokedWhenAnimationIsCancelled() { flagNotificationAsHun() controller.onLaunchAnimationCancelled() @@ -80,10 +83,11 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { assertFalse(notification.entry.isExpandAnimationRunning) verify(headsUpManager).removeNotification( notificationKey, true /* releaseImmediately */, true /* animate */) + verify(onFinishAnimationCallback).run() } @Test - fun testHunIsRemovedWhenAnimationEnds() { + fun testHunIsRemovedAndCallbackIsInvokedWhenAnimationEnds() { flagNotificationAsHun() controller.onLaunchAnimationEnd(isExpandingFullyAbove = true) @@ -91,6 +95,7 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { assertFalse(notification.entry.isExpandAnimationRunning) verify(headsUpManager).removeNotification( notificationKey, true /* releaseImmediately */, false /* animate */) + verify(onFinishAnimationCallback).run() } @Test @@ -99,4 +104,4 @@ class NotificationLaunchAnimatorControllerTest : SysuiTestCase() { assertTrue(notification.entry.isExpandAnimationRunning) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt index 144eefb17283..699f77f9b7bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt @@ -170,11 +170,41 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { } @Test + fun testCancelAndReAddStickyNotification() { + whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true) + addHUN(mEntry) + whenever(mHeadsUpManager.canRemoveImmediately(anyString())).thenReturn(false, true, false) + whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L) + assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0)) + addHUN(mEntry) + assertFalse(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0)) + mExecutor.advanceClockToLast() + mExecutor.runAllReady() + assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0)) + verify(mHeadsUpManager, times(0)).removeNotification(anyString(), eq(false)) + verify(mHeadsUpManager, times(0)).removeNotification(anyString(), eq(true)) + } + + @Test + fun hunNotRemovedWhenExtensionCancelled() { + whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true) + addHUN(mEntry) + whenever(mHeadsUpManager.canRemoveImmediately(anyString())).thenReturn(false) + whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L) + assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0)) + mNotifLifetimeExtender.cancelLifetimeExtension(mEntry) + mExecutor.advanceClockToLast() + mExecutor.runAllReady() + verify(mHeadsUpManager, times(0)).removeNotification(anyString(), any()) + } + + @Test fun testCancelUpdatedStickyNotification() { whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true) addHUN(mEntry) whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L, 500L) assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0)) + addHUN(mEntry) mExecutor.advanceClockToLast() mExecutor.runAllReady() verify(mHeadsUpManager, times(0)).removeNotification(anyString(), eq(false)) @@ -305,6 +335,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { mHuns.add(entry) whenever(mHeadsUpManager.topEntry).thenReturn(entry) mOnHeadsUpChangedListener.onHeadsUpStateChanged(entry, true) + mNotifLifetimeExtender.cancelLifetimeExtension(entry) } @Test 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..52bacd2360b3 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,40 +29,41 @@ 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.Ignore; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +/** + * TODO(b/224771204) Create test cases + */ @SmallTest @RunWith(AndroidTestingRunner.class) +@Ignore public class KeyguardCoordinatorTest 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 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 +72,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 +85,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/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 27179fd7be92..d48ce8c6803e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -85,6 +85,7 @@ import com.android.systemui.wmshell.BubblesManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; @@ -188,10 +189,11 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false); when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry())) .thenReturn(null); - when(mVisibilityProvider.obtain(anyString(), anyBoolean())).thenAnswer( - invocation-> NotificationVisibility.obtain(invocation.getArgument(0), 0, 1, false)); - when(mVisibilityProvider.obtain(any(NotificationEntry.class), anyBoolean())).thenAnswer( - invocation-> NotificationVisibility.obtain( + when(mVisibilityProvider.obtain(anyString(), anyBoolean())) + .thenAnswer(invocation -> NotificationVisibility.obtain( + invocation.getArgument(0), 0, 1, false)); + when(mVisibilityProvider.obtain(any(NotificationEntry.class), anyBoolean())) + .thenAnswer(invocation -> NotificationVisibility.obtain( invocation.<NotificationEntry>getArgument(0).getKey(), 0, 1, false)); HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class); @@ -431,12 +433,18 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { } @Test - public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse() { + public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse() + throws Exception { NotifActivityLaunchEvents.Listener listener = mock(NotifActivityLaunchEvents.Listener.class); mLaunchEventsEmitter.registerListener(listener); mNotificationActivityStarter .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow); + ArgumentCaptor<ActivityLaunchAnimator.Controller> controllerCaptor = + ArgumentCaptor.forClass(ActivityLaunchAnimator.Controller.class); + verify(mActivityLaunchAnimator).startPendingIntentWithAnimation( + controllerCaptor.capture(), anyBoolean(), any(), any()); + controllerCaptor.getValue().onIntentStarted(false); verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java index 20a3fdaa99a5..3a0a7c9d80fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java @@ -114,15 +114,13 @@ public class RemoteInputViewTest extends SysuiTestCase { mContext.unregisterReceiver(mReceiver); } - private void setTestPendingIntent(RemoteInputView view, RemoteInputViewController controller) { + private void setTestPendingIntent(RemoteInputViewController controller) { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(TEST_ACTION), PendingIntent.FLAG_MUTABLE); RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).build(); RemoteInput[] inputs = {input}; - view.setPendingIntent(pendingIntent); controller.setPendingIntent(pendingIntent); - view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */); controller.setRemoteInput(input); controller.setRemoteInputs(inputs); } @@ -137,7 +135,7 @@ public class RemoteInputViewTest extends SysuiTestCase { RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); RemoteInputViewController controller = bindController(view, row.getEntry()); - setTestPendingIntent(view, controller); + setTestPendingIntent(controller); view.focus(); @@ -177,7 +175,7 @@ public class RemoteInputViewTest extends SysuiTestCase { RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); RemoteInputViewController controller = bindController(view, row.getEntry()); - setTestPendingIntent(view, controller); + setTestPendingIntent(controller); view.focus(); @@ -235,7 +233,7 @@ public class RemoteInputViewTest extends SysuiTestCase { RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); RemoteInputViewController controller = bindController(view, row.getEntry()); - setTestPendingIntent(view, controller); + setTestPendingIntent(controller); // Open view, send a reply view.focus(); @@ -265,7 +263,7 @@ public class RemoteInputViewTest extends SysuiTestCase { RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); RemoteInputViewController controller = bindController(view, row.getEntry()); - setTestPendingIntent(view, controller); + setTestPendingIntent(controller); // Open view, attach an image view.focus(); 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/proto/src/camera.proto b/proto/src/camera.proto index 40821185b61a..38d74e4a73ce 100644 --- a/proto/src/camera.proto +++ b/proto/src/camera.proto @@ -66,5 +66,5 @@ message CameraStreamProto { // The dynamic range profile of the stream optional int64 dynamic_range_profile = 14; // The stream use case - optional int32 stream_use_case = 15; + optional int64 stream_use_case = 15; } diff --git a/services/api/current.txt b/services/api/current.txt index 45c00595841d..5a2880223f6c 100644 --- a/services/api/current.txt +++ b/services/api/current.txt @@ -38,7 +38,7 @@ package com.android.server { package com.android.server.am { public interface ActivityManagerLocal { - method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, int) throws android.os.RemoteException; + method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException; method public boolean canStartForegroundService(int, int, @NonNull String); } diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index e10151dbd04b..1af35af9fc17 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -89,8 +89,6 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; -import android.os.storage.IStorageManager; -import android.os.storage.StorageManager; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; @@ -325,7 +323,6 @@ public class UserBackupManagerService { private final ActivityManagerInternal mActivityManagerInternal; private PowerManager mPowerManager; private final AlarmManager mAlarmManager; - private final IStorageManager mStorageManager; private final BackupManagerConstants mConstants; private final BackupWakeLock mWakelock; private final BackupHandler mBackupHandler; @@ -536,7 +533,6 @@ public class UserBackupManagerService { mBackupPasswordManager = null; mPackageManagerBinder = null; mActivityManager = null; - mStorageManager = null; mBackupManagerBinder = null; mScheduledBackupEligibility = null; } @@ -560,7 +556,6 @@ public class UserBackupManagerService { mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount")); Objects.requireNonNull(parent, "parent cannot be null"); mBackupManagerBinder = BackupManagerService.asInterface(parent.asBinder()); @@ -2077,26 +2072,6 @@ public class UserBackupManagerService { } } - /** For adb backup/restore. */ - public boolean deviceIsEncrypted() { - try { - return mStorageManager.getEncryptionState() - != StorageManager.ENCRYPTION_STATE_NONE - && mStorageManager.getPasswordType() - != StorageManager.CRYPT_TYPE_DEFAULT; - } catch (Exception e) { - // If we can't talk to the storagemanager service we have a serious problem; fail - // "secure" i.e. assuming that the device is encrypted. - Slog.e( - TAG, - addUserIdToLogMessage( - mUserId, - "Unable to communicate with storagemanager service: " - + e.getMessage())); - return true; - } - } - // ----- Full-data backup scheduling ----- /** diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java index 7ee307e30dce..ec58e17148b3 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java +++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java @@ -320,12 +320,6 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor try { boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0); - // Only allow encrypted backups of encrypted devices - if (mUserBackupManagerService.deviceIsEncrypted() && !encrypting) { - Slog.e(TAG, "Unencrypted backup of encrypted device; aborting"); - return; - } - OutputStream finalOutput = ofstream; // Verify that the given password matches the currently-active diff --git a/services/companion/java/com/android/server/companion/CompanionApplicationController.java b/services/companion/java/com/android/server/companion/CompanionApplicationController.java index f32eebc2a31f..2a83a3c431ec 100644 --- a/services/companion/java/com/android/server/companion/CompanionApplicationController.java +++ b/services/companion/java/com/android/server/companion/CompanionApplicationController.java @@ -49,7 +49,7 @@ import java.util.Map; * The following is the list of the APIs provided by {@link CompanionApplicationController} (to be * utilized by {@link CompanionDeviceManagerService}): * <ul> - * <li> {@link #bindCompanionApplication(int, String)} + * <li> {@link #bindCompanionApplication(int, String, boolean)} * <li> {@link #unbindCompanionApplication(int, String)} * <li> {@link #notifyCompanionApplicationDeviceAppeared(AssociationInfo)} * <li> {@link #notifyCompanionApplicationDeviceDisappeared(AssociationInfo)} @@ -103,8 +103,12 @@ class CompanionApplicationController { mCompanionServicesRegister.invalidate(userId); } - void bindCompanionApplication(@UserIdInt int userId, @NonNull String packageName) { - if (DEBUG) Log.i(TAG, "bind() u" + userId + "/" + packageName); + void bindCompanionApplication(@UserIdInt int userId, @NonNull String packageName, + boolean bindImportant) { + if (DEBUG) { + Log.i(TAG, "bind() u" + userId + "/" + packageName + + " important=" + bindImportant); + } final List<ComponentName> companionServices = mCompanionServicesRegister.forPackage(userId, packageName); @@ -125,7 +129,8 @@ class CompanionApplicationController { } serviceConnectors = CollectionUtils.map(companionServices, componentName -> - new CompanionDeviceServiceConnector(mContext, userId, componentName)); + CompanionDeviceServiceConnector.newInstance(mContext, userId, + componentName, bindImportant)); mBoundCompanionApplications.setValueForPackage(userId, packageName, serviceConnectors); } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index eaa99f74e24e..13a5a2829945 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -254,9 +254,12 @@ public class CompanionDeviceManagerService extends SystemService { final int userId = association.getUserId(); final String packageName = association.getPackageName(); + // Set bindImportant to true when the association is self-managed to avoid the target + // service being killed. + final boolean bindImportant = association.isSelfManaged(); if (!mCompanionAppController.isCompanionApplicationBound(userId, packageName)) { - mCompanionAppController.bindCompanionApplication(userId, packageName); + mCompanionAppController.bindCompanionApplication(userId, packageName, bindImportant); } else if (DEBUG) { Log.i(TAG, "u" + userId + "\\" + packageName + " is already bound"); } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java index f2a58b74a65a..4c7b9b80d5be 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java @@ -16,6 +16,7 @@ package com.android.server.companion; +import static android.content.Context.BIND_ALMOST_PERCEPTIBLE; import static android.content.Context.BIND_IMPORTANT; import static android.os.Process.THREAD_PRIORITY_DEFAULT; @@ -44,20 +45,43 @@ import com.android.server.ServiceThread; class CompanionDeviceServiceConnector extends ServiceConnector.Impl<ICompanionDeviceService> { private static final String TAG = "CompanionDevice_ServiceConnector"; private static final boolean DEBUG = false; - private static final int BINDING_FLAGS = BIND_IMPORTANT; /** Listener for changes to the state of the {@link CompanionDeviceServiceConnector} */ interface Listener { void onBindingDied(@UserIdInt int userId, @NonNull String packageName); } - private final @UserIdInt int mUserId; - private final @NonNull ComponentName mComponentName; - private @Nullable Listener mListener; + @UserIdInt + private final int mUserId; + @NonNull + private final ComponentName mComponentName; + @Nullable + private Listener mListener; - CompanionDeviceServiceConnector(@NonNull Context context, @UserIdInt int userId, - @NonNull ComponentName componentName) { - super(context, buildIntent(componentName), BINDING_FLAGS, userId, null); + /** + * Create a CompanionDeviceServiceConnector instance. + * + * When bindImportant is false, the binding flag will be BIND_ALMOST_PERCEPTIBLE + * (oom_score_adj = PERCEPTIBLE_MEDIUM_APP = 225). The target service will be treated + * as important as a perceptible app (IMPORTANCE_VISIBLE = 200), and will be unbound when + * the app is removed from task manager. + * When bindImportant is true, the binding flag will be BIND_IMPORTANT + * (oom_score_adj = PERCEPTIBLE_MEDIUM_APP = -700). The target service will + * have the highest priority to avoid being killed (IMPORTANCE_FOREGROUND = 100). + * + * One time permission's importance level to keep session alive is + * IMPORTANCE_FOREGROUND_SERVICE = 125. In order to kill the one time permission session, the + * service importance level should be higher than 125. + */ + static CompanionDeviceServiceConnector newInstance(@NonNull Context context, + @UserIdInt int userId, @NonNull ComponentName componentName, boolean bindImportant) { + final int bindingFlags = bindImportant ? BIND_IMPORTANT : BIND_ALMOST_PERCEPTIBLE; + return new CompanionDeviceServiceConnector(context, userId, componentName, bindingFlags); + } + + private CompanionDeviceServiceConnector(@NonNull Context context, @UserIdInt int userId, + @NonNull ComponentName componentName, int bindingFlags) { + super(context, buildIntent(componentName), bindingFlags, userId, null); mUserId = userId; mComponentName = componentName; } diff --git a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java index 1ba198ae26b0..823743da7da6 100644 --- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java +++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java @@ -94,7 +94,7 @@ class BluetoothCompanionDeviceConnectionListener int reason) { if (DEBUG) { Log.i(TAG, "onDevice_Disconnected() " + btDeviceToString(device)); - Log.d(TAG, " reason=" + disconnectReasonText(reason)); + Log.d(TAG, " reason=" + disconnectReasonToString(reason)); } final MacAddress macAddress = MacAddress.fromString(device.getAddress()); diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index b991ba87eef4..3a26c4611629 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.WindowConfiguration; import android.app.compat.CompatChanges; import android.companion.virtual.VirtualDeviceManager.ActivityListener; import android.companion.virtual.VirtualDeviceParams; @@ -119,6 +120,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @ActivityPolicy int defaultActivityPolicy, @NonNull ActivityListener activityListener, @NonNull Consumer<ActivityInfo> activityBlockedCallback) { + super(); mAllowedUsers = allowedUsers; mAllowedActivities = new ArraySet<>(allowedActivities); mBlockedActivities = new ArraySet<>(blockedActivities); @@ -134,7 +136,11 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController } @Override - public boolean canContainActivities(@NonNull List<ActivityInfo> activities) { + public boolean canContainActivities(@NonNull List<ActivityInfo> activities, + @WindowConfiguration.WindowingMode int windowingMode) { + if (!isWindowingModeSupported(windowingMode)) { + return false; + } // Can't display all the activities if any of them don't want to be displayed. final int activityCount = activities.size(); for (int i = 0; i < activityCount; i++) { 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/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index be2b7f72bd4f..f1fa982d0234 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -131,7 +131,7 @@ public class MasterClearReceiver extends BroadcastReceiver { final UserManager userManager = context.getSystemService(UserManager.class); final int result = userManager.removeUserWhenPossible( UserHandle.of(userId), /* overrideDevicePolicy= */ false); - if (result == UserManager.REMOVE_RESULT_ERROR) { + if (!UserManager.isRemoveResultSuccessful(result)) { Slogf.e(TAG, "Can't remove user %d", userId); return false; } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 7075ed34dfb4..677fc7931f64 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -3129,203 +3129,6 @@ class StorageManagerService extends IStorageManager.Stub } } - @Override - public int getEncryptionState() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - try { - return mVold.fdeComplete(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; - } - } - - @Override - public int decryptStorage(String password) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - if (TextUtils.isEmpty(password)) { - throw new IllegalArgumentException("password cannot be empty"); - } - - if (DEBUG_EVENTS) { - Slog.i(TAG, "decrypting storage..."); - } - - try { - mVold.fdeCheckPassword(password); - mHandler.postDelayed(() -> { - try { - mVold.fdeRestart(); - } catch (Exception e) { - Slog.wtf(TAG, e); - } - }, DateUtils.SECOND_IN_MILLIS); - return 0; - } catch (ServiceSpecificException e) { - Slog.e(TAG, "fdeCheckPassword failed", e); - return e.errorCode; - } catch (Exception e) { - Slog.wtf(TAG, e); - return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; - } - } - - @Override - public int encryptStorage(int type, String password) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - if (type == StorageManager.CRYPT_TYPE_DEFAULT) { - password = ""; - } else if (TextUtils.isEmpty(password)) { - throw new IllegalArgumentException("password cannot be empty"); - } - - if (DEBUG_EVENTS) { - Slog.i(TAG, "encrypting storage..."); - } - - try { - mVold.fdeEnable(type, password, 0); - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - - return 0; - } - - /** Set the password for encrypting the main key. - * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager. - * @param password The password to set. - */ - @Override - public int changeEncryptionPassword(int type, String password) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - if (StorageManager.isFileEncryptedNativeOnly()) { - // Not supported on FBE devices - return -1; - } - - if (type == StorageManager.CRYPT_TYPE_DEFAULT) { - password = ""; - } else if (TextUtils.isEmpty(password)) { - throw new IllegalArgumentException("password cannot be empty"); - } - - if (DEBUG_EVENTS) { - Slog.i(TAG, "changing encryption password..."); - } - - try { - mVold.fdeChangePassword(type, password); - return 0; - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - } - - /** - * Validate a user-supplied password string with cryptfs - */ - @Override - public int verifyEncryptionPassword(String password) throws RemoteException { - // Only the system process is permitted to validate passwords - if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { - throw new SecurityException("no permission to access the crypt keeper"); - } - - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - if (TextUtils.isEmpty(password)) { - throw new IllegalArgumentException("password cannot be empty"); - } - - if (DEBUG_EVENTS) { - Slog.i(TAG, "validating encryption password..."); - } - - try { - mVold.fdeVerifyPassword(password); - return 0; - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - } - - /** - * Get the type of encryption used to encrypt the main key. - * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager. - */ - @Override - public int getPasswordType() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - try { - return mVold.fdeGetPasswordType(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - } - - /** - * Set a field in the crypto header. - * @param field field to set - * @param contents contents to set in field - */ - @Override - public void setField(String field, String contents) throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - if (!StorageManager.isBlockEncrypted()) { - // Only supported on FDE devices - return; - } - - try { - mVold.fdeSetField(field, contents); - return; - } catch (Exception e) { - Slog.wtf(TAG, e); - return; - } - } - - /** - * Gets a field from the crypto header. - * @param field field to get - * @return contents of field - */ - @Override - public String getField(String field) throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "no permission to access the crypt keeper"); - - if (!StorageManager.isBlockEncrypted()) { - // Only supported on FDE devices - return null; - } - - try { - return mVold.fdeGetField(field); - } catch (Exception e) { - Slog.wtf(TAG, e); - return null; - } - } - /** * Is userdata convertible to file based encryption? * @return non zero for convertible @@ -3408,33 +3211,6 @@ class StorageManagerService extends IStorageManager.Stub } @Override - public String getPassword() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "only keyguard can retrieve password"); - - try { - return mVold.fdeGetPassword(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return null; - } - } - - @Override - public void clearPassword() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, - "only keyguard can clear password"); - - try { - mVold.fdeClearPassword(); - return; - } catch (Exception e) { - Slog.wtf(TAG, e); - return; - } - } - - @Override public void createUserKey(int userId, int serialNumber, boolean ephemeral) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 58fa9fb28a78..839cdc6eaca3 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -91,7 +91,7 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; -import com.android.internal.telephony.ICarrierPrivilegesListener; +import com.android.internal.telephony.ICarrierPrivilegesCallback; import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.ITelephonyRegistry; @@ -153,7 +153,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { IPhoneStateListener callback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback; - ICarrierPrivilegesListener carrierPrivilegesListener; + ICarrierPrivilegesCallback carrierPrivilegesCallback; int callerUid; int callerPid; @@ -178,8 +178,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return (onOpportunisticSubscriptionsChangedListenerCallback != null); } - boolean matchCarrierPrivilegesListener() { - return carrierPrivilegesListener != null; + boolean matchCarrierPrivilegesCallback() { + return carrierPrivilegesCallback != null; } boolean canReadCallLog() { @@ -199,7 +199,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" + onOpportunisticSubscriptionsChangedListenerCallback - + " carrierPrivilegesListener=" + carrierPrivilegesListener + + " carrierPrivilegesCallback=" + carrierPrivilegesCallback + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}"; } } @@ -414,7 +414,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates; /** Per-phoneId snapshot of privileged packages (names + UIDs). */ - private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates; + @NonNull private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates; + /** Per-phoneId of CarrierService (PackageName, UID) pair. */ + @NonNull private List<Pair<String, Integer>> mCarrierServiceStates; /** * Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}. @@ -705,6 +707,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mPhysicalChannelConfigs, mNumPhones); cutListToSize(mLinkCapacityEstimateLists, mNumPhones); cutListToSize(mCarrierPrivilegeStates, mNumPhones); + cutListToSize(mCarrierServiceStates, mNumPhones); return; } @@ -746,6 +749,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mAllowedNetworkTypeValue[i] = -1; mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); + mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID)); } } } @@ -813,6 +817,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataEnabledReason = new int[numPhones]; mLinkCapacityEstimateLists = new ArrayList<>(); mCarrierPrivilegeStates = new ArrayList<>(); + mCarrierServiceStates = new ArrayList<>(); for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; @@ -851,6 +856,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mAllowedNetworkTypeValue[i] = -1; mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); + mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID)); } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -2784,16 +2790,16 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void addCarrierPrivilegesListener( + public void addCarrierPrivilegesCallback( int phoneId, - ICarrierPrivilegesListener callback, - String callingPackage, - String callingFeatureId) { + @NonNull ICarrierPrivilegesCallback callback, + @NonNull String callingPackage, + @NonNull String callingFeatureId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, - "addCarrierPrivilegesListener"); + "addCarrierPrivilegesCallback"); if (VDBG) { log( "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId @@ -2813,7 +2819,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (r == null) return; r.context = mContext; - r.carrierPrivilegesListener = callback; + r.carrierPrivilegesCallback = callback; r.callingPackage = callingPackage; r.callingFeatureId = callingFeatureId; r.callerUid = Binder.getCallingUid(); @@ -2825,10 +2831,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId); + Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(phoneId); try { - r.carrierPrivilegesListener.onCarrierPrivilegesChanged( - Collections.unmodifiableList(state.first), - Arrays.copyOf(state.second, state.second.length)); + if (r.matchCarrierPrivilegesCallback()) { + // Here, two callbacks are triggered in quick succession on the same binder. + // In typical case, we expect the callers to care about only one or the other. + r.carrierPrivilegesCallback.onCarrierPrivilegesChanged( + Collections.unmodifiableList(state.first), + Arrays.copyOf(state.second, state.second.length)); + + r.carrierPrivilegesCallback.onCarrierServiceChanged(carrierServiceState.first, + carrierServiceState.second); + } } catch (RemoteException ex) { remove(r.binder); } @@ -2836,12 +2850,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void removeCarrierPrivilegesListener( - ICarrierPrivilegesListener callback, String callingPackage) { + public void removeCarrierPrivilegesCallback( + @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage) { mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, - "removeCarrierPrivilegesListener"); + "removeCarrierPrivilegesCallback"); remove(callback.asBinder()); } @@ -2866,13 +2880,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { // Listeners are per-slot, not per-subscription. This is to provide a stable // view across SIM profile switches. - if (!r.matchCarrierPrivilegesListener() + if (!r.matchCarrierPrivilegesCallback() || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) { continue; } try { // Make sure even in-process listeners can't modify the values. - r.carrierPrivilegesListener.onCarrierPrivilegesChanged( + r.carrierPrivilegesCallback.onCarrierPrivilegesChanged( Collections.unmodifiableList(privilegedPackageNames), Arrays.copyOf(privilegedUids, privilegedUids.length)); } catch (RemoteException ex) { @@ -2883,6 +2897,34 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + @Override + public void notifyCarrierServiceChanged(int phoneId, @Nullable String packageName, int uid) { + if (!checkNotifyPermission("notifyCarrierServiceChanged")) return; + if (!validatePhoneId(phoneId)) return; + if (VDBG) { + log("notifyCarrierServiceChanged: phoneId=" + phoneId + + ", package=" + pii(packageName) + ", uid=" + uid); + } + + synchronized (mRecords) { + mCarrierServiceStates.set( + phoneId, new Pair<>(packageName, uid)); + for (Record r : mRecords) { + // Listeners are per-slot, not per-subscription. + if (!r.matchCarrierPrivilegesCallback() + || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) { + continue; + } + try { + r.carrierPrivilegesCallback.onCarrierServiceChanged(packageName, uid); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + handleRemoveListLocked(); + } + } + @NeverCompile // Avoid size overhead of debugging code. @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -2938,6 +2980,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println( "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first) + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">"); + Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i); + pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first) + + ", uid=" + carrierServiceState.second + ">"); pw.decreaseIndent(); } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index d4ad718fbe73..48e3264b2c11 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2722,7 +2722,7 @@ public final class ActiveServices { int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid, - String callingPackage, final int userId) + String sdkSandboxClientAppPackage, String callingPackage, final int userId) throws TransactionTooLargeException { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service + " type=" + resolvedType + " conn=" + connection.asBinder() @@ -2807,8 +2807,9 @@ public final class ActiveServices { final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0; ServiceLookupResult res = retrieveServiceLocked(service, instanceName, - isSdkSandboxService, sdkSandboxClientAppUid, resolvedType, callingPackage, - callingPid, callingUid, userId, true, callerFg, isBindExternal, allowInstant); + isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage, + resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, + isBindExternal, allowInstant); if (res == null) { return 0; } @@ -3228,14 +3229,14 @@ public final class ActiveServices { int callingPid, int callingUid, int userId, boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal, boolean allowInstant) { - return retrieveServiceLocked(service, instanceName, false, 0, resolvedType, callingPackage, - callingPid, callingUid, userId, createIfNeeded, callingFromFg, isBindExternal, - allowInstant); + return retrieveServiceLocked(service, instanceName, false, 0, null, resolvedType, + callingPackage, callingPid, callingUid, userId, createIfNeeded, callingFromFg, + isBindExternal, allowInstant); } private ServiceLookupResult retrieveServiceLocked(Intent service, String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid, - String resolvedType, + String sdkSandboxClientAppPackage, String resolvedType, String callingPackage, int callingPid, int callingUid, int userId, boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal, boolean allowInstant) { @@ -3416,7 +3417,8 @@ public final class ActiveServices { : null; r = new ServiceRecord(mAm, className, name, definingPackageName, definingUid, filter, sInfo, callingFromFg, res, - sdkSandboxProcessName, sdkSandboxClientAppUid); + sdkSandboxProcessName, sdkSandboxClientAppUid, + sdkSandboxClientAppPackage); res.setService(r); smap.mServicesByInstanceName.put(name, r); smap.mServicesByIntent.put(filter, r); @@ -4195,7 +4197,7 @@ public final class ActiveServices { if (r.isSdkSandbox) { final int uid = Process.toSdkSandboxUid(r.sdkSandboxClientAppUid); app = mAm.startSdkSandboxProcessLocked(procName, r.appInfo, true, intentFlags, - hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, uid); + hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, uid, r.sdkSandboxClientAppPackage); r.isolationHostProc = app; } else { app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 18e0155cfd34..c42666247e98 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -127,7 +127,15 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE = "kill_bg_restricted_cached_idle"; static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME = "kill_bg_restricted_cached_idle_settle_time"; + /** + * Note this key is on {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS}. + * @see #mEnableComponentAlias + */ static final String KEY_ENABLE_COMPONENT_ALIAS = "enable_experimental_component_alias"; + /** + * Note this key is on {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS}. + * @see #mComponentAliasOverrides + */ static final String KEY_COMPONENT_ALIAS_OVERRIDES = "component_alias_overrides"; private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; @@ -899,10 +907,6 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE: updateEnableExtraServiceRestartDelayOnMemPressure(); break; - case KEY_ENABLE_COMPONENT_ALIAS: - case KEY_COMPONENT_ALIAS_OVERRIDES: - updateComponentAliases(); - break; case KEY_PROCESS_KILL_TIMEOUT: updateProcessKillTimeout(); break; @@ -925,6 +929,26 @@ final class ActivityManagerConstants extends ContentObserver { } }; + private final OnPropertiesChangedListener mOnDeviceConfigChangedForComponentAliasListener = + new OnPropertiesChangedListener() { + @Override + public void onPropertiesChanged(Properties properties) { + for (String name : properties.getKeyset()) { + if (name == null) { + return; + } + switch (name) { + case KEY_ENABLE_COMPONENT_ALIAS: + case KEY_COMPONENT_ALIAS_OVERRIDES: + updateComponentAliases(); + break; + default: + break; + } + } + } + }; + ActivityManagerConstants(Context context, ActivityManagerService service, Handler handler) { super(handler); mService = service; @@ -991,6 +1015,10 @@ final class ActivityManagerConstants extends ContentObserver { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ActivityThread.currentApplication().getMainExecutor(), mOnDeviceConfigChangedListener); + DeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS, + ActivityThread.currentApplication().getMainExecutor(), + mOnDeviceConfigChangedForComponentAliasListener); loadDeviceConfigConstants(); // The following read from Settings. updateActivityStartsLoggingEnabled(); @@ -1000,6 +1028,9 @@ final class ActivityManagerConstants extends ContentObserver { private void loadDeviceConfigConstants() { mOnDeviceConfigChangedListener.onPropertiesChanged( DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER)); + mOnDeviceConfigChangedForComponentAliasListener.onPropertiesChanged( + DeviceConfig.getProperties( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS)); } public void setOverrideMaxCachedProcesses(int value) { @@ -1379,11 +1410,11 @@ final class ActivityManagerConstants extends ContentObserver { private void updateComponentAliases() { mEnableComponentAlias = DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS, KEY_ENABLE_COMPONENT_ALIAS, DEFAULT_ENABLE_COMPONENT_ALIAS); mComponentAliasOverrides = DeviceConfig.getString( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS, KEY_COMPONENT_ALIAS_OVERRIDES, DEFAULT_COMPONENT_ALIAS_OVERRIDES); mService.mComponentAliasResolver.update(mEnableComponentAlias, mComponentAliasOverrides); diff --git a/services/core/java/com/android/server/am/ActivityManagerLocal.java b/services/core/java/com/android/server/am/ActivityManagerLocal.java index 3226a2b58a96..1d2c36b63bda 100644 --- a/services/core/java/com/android/server/am/ActivityManagerLocal.java +++ b/services/core/java/com/android/server/am/ActivityManagerLocal.java @@ -74,6 +74,8 @@ public interface ActivityManagerLocal { * @param conn Receives information as the service is started and stopped. * This must be a valid ServiceConnection object; it must not be null. * @param clientAppUid Uid of the app for which the sdk sandbox process needs to be spawned. + * @param clientAppPackage Package of the app for which the sdk sandbox process needs to + * be spawned. This package must belong to the clientAppUid. * @param processName Unique identifier for the service instance. Each unique name here will * result in a different service instance being created. Identifiers must only contain * ASCII letters, digits, underscores, and periods. @@ -87,6 +89,7 @@ public interface ActivityManagerLocal { */ @SuppressLint("RethrowRemoteException") boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn, - int clientAppUid, @NonNull String processName, @Context.BindServiceFlags int flags) + int clientAppUid, @NonNull String clientAppPackage, @NonNull String processName, + @Context.BindServiceFlags int flags) throws RemoteException; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 95e35ef6cf32..0735648c1069 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -36,6 +36,7 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManager.StopUserOnSwitch; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; +import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_NONE; import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT; import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES; @@ -1895,6 +1896,7 @@ public class ActivityManagerService extends IActivityManager.Stub 0, false, 0, + null, new HostingRecord("system")); app.setPersistent(true); app.setPid(MY_PID); @@ -2783,7 +2785,8 @@ public class ActivityManagerService extends IActivityManager.Stub false /* knownToBeDead */, 0 /* intentFlags */, sNullHostingRecord /* hostingRecord */, ZYGOTE_POLICY_FLAG_EMPTY, true /* allowWhileBooting */, true /* isolated */, - uid, false /* supplemental */, 0 /* supplementalUid */, + uid, false /* isSdkSandbox */, 0 /* sdkSandboxUid */, + null /* sdkSandboxClientAppPackage */, abiOverride, entryPoint, entryPointArgs, crashHandler); return proc != null; } @@ -2792,11 +2795,12 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final ProcessRecord startSdkSandboxProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, - HostingRecord hostingRecord, int zygotePolicyFlags, int sdkSandboxUid) { + HostingRecord hostingRecord, int zygotePolicyFlags, int sdkSandboxUid, + String sdkSandboxClientAppPackage) { return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, zygotePolicyFlags, false /* allowWhileBooting */, false /* isolated */, 0 /* isolatedUid */, - true /* isSdkSandbox */, sdkSandboxUid, + true /* isSdkSandbox */, sdkSandboxUid, sdkSandboxClientAppPackage, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); } @@ -2808,7 +2812,8 @@ public class ActivityManagerService extends IActivityManager.Stub boolean isolated) { return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */, - false /* isSdkSandbox */, 0 /* sdkSandboxClientdAppUid */, + false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */, + null /* sdkSandboxClientAppPackage */, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); } @@ -4773,7 +4778,8 @@ public class ActivityManagerService extends IActivityManager.Stub thread.runIsolatedEntryPoint( app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs()); } else if (instr2 != null) { - thread.bindApplication(processName, appInfo, providerList, + thread.bindApplication(processName, appInfo, app.sdkSandboxClientAppPackage, + providerList, instr2.mClass, profilerInfo, instr2.mArguments, instr2.mWatcher, @@ -4787,8 +4793,8 @@ public class ActivityManagerService extends IActivityManager.Stub app.getDisabledCompatChanges(), serializedSystemFontMap, app.getStartElapsedTime(), app.getStartUptime()); } else { - thread.bindApplication(processName, appInfo, providerList, null, profilerInfo, - null, null, null, testMode, + thread.bindApplication(processName, appInfo, app.sdkSandboxClientAppPackage, + providerList, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), @@ -5749,6 +5755,18 @@ public class ActivityManagerService extends IActivityManager.Stub owningUid, exported); } + private void enforceDebuggable(ProcessRecord proc) { + if (!Build.IS_DEBUGGABLE && !proc.isDebuggable()) { + throw new SecurityException("Process not debuggable: " + proc.info.packageName); + } + } + + private void enforceDebuggable(ApplicationInfo info) { + if (!Build.IS_DEBUGGABLE && (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) { + throw new SecurityException("Process not debuggable: " + info.packageName); + } + } + /** * As the only public entry point for permissions checking, this method * can enforce the semantic that requesting a check on a null global @@ -6553,7 +6571,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (app == null) { app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0, - false, 0, + false, 0, null, new HostingRecord("added application", customProcess != null ? customProcess : info.processName)); updateLruProcessLocked(app, false, null); @@ -6786,22 +6804,25 @@ public class ActivityManagerService extends IActivityManager.Stub } void setTrackAllocationApp(ApplicationInfo app, String processName) { - if (!Build.IS_DEBUGGABLE) { - if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) { - throw new SecurityException("Process not debuggable: " + app.packageName); - } - } + enforceDebuggable(app); synchronized (mProcLock) { mTrackAllocationApp = processName; } } - void setProfileApp(ApplicationInfo app, String processName, ProfilerInfo profilerInfo) { + void setProfileApp(ApplicationInfo app, String processName, ProfilerInfo profilerInfo, + ApplicationInfo sdkSandboxClientApp) { synchronized (mAppProfiler.mProfilerLock) { if (!Build.IS_DEBUGGABLE) { boolean isAppDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; boolean isAppProfileable = app.isProfileableByShell(); + + if (sdkSandboxClientApp != null) { + isAppDebuggable |= + (sdkSandboxClientApp.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + isAppProfileable |= sdkSandboxClientApp.isProfileableByShell(); + } if (!isAppDebuggable && !isAppProfileable) { throw new SecurityException("Process not debuggable, " + "and not profileable by shell: " + app.packageName); @@ -6812,11 +6833,7 @@ public class ActivityManagerService extends IActivityManager.Stub } void setNativeDebuggingAppLocked(ApplicationInfo app, String processName) { - if (!Build.IS_DEBUGGABLE) { - if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) { - throw new SecurityException("Process not debuggable: " + app.packageName); - } - } + enforceDebuggable(app); mNativeDebuggingApp = processName; } @@ -12395,13 +12412,13 @@ public class ActivityManagerService extends IActivityManager.Stub String resolvedType, IServiceConnection connection, int flags, String instanceName, String callingPackage, int userId) throws TransactionTooLargeException { return bindServiceInstance(caller, token, service, resolvedType, connection, flags, - instanceName, false, 0, callingPackage, userId); + instanceName, false, 0, null, callingPackage, userId); } private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String instanceName, - boolean isSdkSandboxService, int sdkSandboxClientdAppUid, String callingPackage, - int userId) + boolean isSdkSandboxService, int sdkSandboxClientAppUid, + String sdkSandboxClientAppPackage, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); @@ -12438,8 +12455,8 @@ public class ActivityManagerService extends IActivityManager.Stub } synchronized (this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, - flags, instanceName, isSdkSandboxService, sdkSandboxClientdAppUid, - callingPackage, userId); + flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid, + sdkSandboxClientAppPackage, callingPackage, userId); } } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); @@ -15562,12 +15579,7 @@ public class ActivityManagerService extends IActivityManager.Stub throw new IllegalArgumentException("Unknown process: " + process); } - boolean isDebuggable = Build.IS_DEBUGGABLE; - if (!isDebuggable) { - if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) { - throw new SecurityException("Process not debuggable: " + proc); - } - } + enforceDebuggable(proc); mOomAdjuster.mCachedAppOptimizer.enableFreezer(false); @@ -15670,10 +15682,7 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException("No process found for calling pid " + Binder.getCallingPid()); } - if (!Build.IS_DEBUGGABLE - && (proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) { - throw new SecurityException("Not running a debuggable build"); - } + enforceDebuggable(proc); processName = proc.processName; uid = proc.uid; if (reportPackage != null && !proc.getPkgList().containsKey(reportPackage)) { @@ -15884,13 +15893,7 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } - if (!Build.IS_DEBUGGABLE) { - if ((process.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) { - return false; - } - } - - return true; + return Build.IS_DEBUGGABLE || process.isDebuggable(); } public boolean startBinderTracking() throws RemoteException { @@ -16022,22 +16025,29 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean bindSdkSandboxService(Intent service, ServiceConnection conn, - int userAppUid, String processName, int flags) throws RemoteException { + int clientAppUid, String clientAppPackage, String processName, int flags) + throws RemoteException { if (service == null) { throw new IllegalArgumentException("intent is null"); } if (conn == null) { throw new IllegalArgumentException("connection is null"); } + if (clientAppPackage == null) { + throw new IllegalArgumentException("clientAppPackage is null"); + } if (processName == null) { throw new IllegalArgumentException("processName is null"); } if (service.getComponent() == null) { throw new IllegalArgumentException("service must specify explicit component"); } - if (!UserHandle.isApp(userAppUid)) { + if (!UserHandle.isApp(clientAppUid)) { throw new IllegalArgumentException("uid is not within application range"); } + if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) { + throw new IllegalArgumentException("uid does not belong to provided package"); + } Handler handler = mContext.getMainThreadHandler(); @@ -16046,8 +16056,8 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManagerService.this.bindServiceInstance( mContext.getIApplicationThread(), mContext.getActivityToken(), service, service.resolveTypeIfNeeded(mContext.getContentResolver()), sd, flags, - processName, /*isSupplementalProcessService*/ true, userAppUid, - mContext.getOpPackageName(), UserHandle.getUserId(userAppUid)) != 0; + processName, /*isSdkSandboxService*/ true, clientAppUid, clientAppPackage, + mContext.getOpPackageName(), UserHandle.getUserId(clientAppUid)) != 0; } @Override @@ -16837,7 +16847,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (profilerInfo != null) { - setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo); + setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo, null); } wmLock.notify(); } @@ -17625,11 +17635,7 @@ public class ActivityManagerService extends IActivityManager.Stub throw new IllegalArgumentException("Unknown process: " + process); } - if (!Build.IS_DEBUGGABLE) { - if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) { - throw new SecurityException("Process not debuggable: " + proc); - } - } + enforceDebuggable(proc); thread.attachAgent(path); } diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java index 7cd45fed1498..ea1e3357c4dc 100644 --- a/services/core/java/com/android/server/am/AppBatteryTracker.java +++ b/services/core/java/com/android/server/am/AppBatteryTracker.java @@ -28,7 +28,6 @@ import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACT import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.BatteryConsumer.POWER_COMPONENT_ANY; import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND; -import static android.os.BatteryConsumer.PROCESS_STATE_COUNT; import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND; import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE; import static android.os.BatteryConsumer.PROCESS_STATE_UNSPECIFIED; @@ -38,7 +37,6 @@ import static android.util.TimeUtils.formatTime; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX; -import static com.android.server.am.BaseAppStateTracker.ONE_MINUTE; import android.annotation.NonNull; import android.annotation.Nullable; @@ -71,7 +69,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.server.am.AppBatteryTracker.AppBatteryPolicy; import com.android.server.am.AppRestrictionController.UidBatteryUsageProvider; -import com.android.server.am.BaseAppStateTracker.Injector; import com.android.server.pm.UserManagerInternal; import java.io.PrintWriter; @@ -684,7 +681,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> static final int BATTERY_USAGE_INDEX_FOREGROUND = PROCESS_STATE_FOREGROUND; static final int BATTERY_USAGE_INDEX_BACKGROUND = PROCESS_STATE_BACKGROUND; static final int BATTERY_USAGE_INDEX_FOREGROUND_SERVICE = PROCESS_STATE_FOREGROUND_SERVICE; - static final int BATTERY_USAGE_COUNT = PROCESS_STATE_COUNT; + static final int BATTERY_USAGE_COUNT = 4; static final Dimensions[] BATT_DIMENS = new Dimensions[] { new Dimensions(AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_POWER_COMPONENTS, diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java index d6a4cf650cba..16a728386bd6 100644 --- a/services/core/java/com/android/server/am/AppProfiler.java +++ b/services/core/java/com/android/server/am/AppProfiler.java @@ -58,7 +58,6 @@ import android.content.ComponentCallbacks2; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Binder; @@ -608,13 +607,7 @@ public class AppProfiler { if (check != null) { if ((pss * 1024) >= check && profile.getThread() != null && mMemWatchDumpProcName == null) { - boolean isDebuggable = Build.IS_DEBUGGABLE; - if (!isDebuggable) { - if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { - isDebuggable = true; - } - } - if (isDebuggable) { + if (Build.IS_DEBUGGABLE || proc.isDebuggable()) { Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting"); startHeapDumpLPf(profile, false); } else { @@ -1702,7 +1695,8 @@ public class AppProfiler { try { if (start) { stopProfilerLPf(null, 0); - mService.setProfileApp(proc.info, proc.processName, profilerInfo); + mService.setProfileApp(proc.info, proc.processName, profilerInfo, + proc.isSdkSandbox ? proc.getClientInfoForSdkSandbox() : null); mProfileData.setProfileProc(proc); mProfileType = profileType; ParcelFileDescriptor fd = profilerInfo.profileFd; @@ -1886,8 +1880,7 @@ public class AppProfiler { BatteryStatsImpl.Uid.Proc ps = st.batteryStats; if (ps == null || !ps.isActive()) { st.batteryStats = ps = bstats.getProcessStatsLocked( - bstats.mapUid(st.uid), st.name, - elapsedRealtime, uptime); + st.uid, st.name, elapsedRealtime, uptime); } ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); } @@ -2076,7 +2069,7 @@ public class AppProfiler { if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) { // We need to do a debuggable check here. See setAgentApp for why the check is // postponed to here. - if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + if (app.isDebuggable()) { String agent = mAppAgentMap.get(processName); // Do not overwrite already requested agent. if (profilerInfo == null) { @@ -2133,7 +2126,7 @@ public class AppProfiler { if (preBindAgent != null) { thread.attachAgent(preBindAgent); } - if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + if (app.isDebuggable()) { thread.attachStartupAgents(app.info.dataDir); } return profilerInfo; diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java index 3577032fb76c..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; @@ -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/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 91822ac353ab..eb7897b2c678 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -799,6 +799,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub final BatteryUsageStatsQuery querySinceReset = new BatteryUsageStatsQuery.Builder() .includeProcessStateData() + .includeVirtualUids() .build(); bus = getBatteryUsageStats(List.of(querySinceReset)).get(0); break; @@ -806,6 +807,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub final BatteryUsageStatsQuery queryPowerProfile = new BatteryUsageStatsQuery.Builder() .includeProcessStateData() + .includeVirtualUids() .powerProfileModeledOnly() .build(); bus = getBatteryUsageStats(List.of(queryPowerProfile)).get(0); @@ -821,6 +823,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub final BatteryUsageStatsQuery queryBeforeReset = new BatteryUsageStatsQuery.Builder() .includeProcessStateData() + .includeVirtualUids() .aggregateSnapshots(sessionStart, sessionEnd) .build(); bus = getBatteryUsageStats(List.of(queryBeforeReset)).get(0); 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/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 48ca59dc4c64..253686c2602d 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -1718,8 +1718,16 @@ public final class ProcessList { int runtimeFlags = 0; boolean debuggableFlag = (app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - if (!debuggableFlag && app.isSdkSandbox) { - debuggableFlag = isAppForSdkSandboxDebuggable(app); + boolean isProfileableByShell = app.info.isProfileableByShell(); + boolean isProfileable = app.info.isProfileable(); + + if (app.isSdkSandbox) { + ApplicationInfo clientInfo = app.getClientInfoForSdkSandbox(); + if (clientInfo != null) { + debuggableFlag |= (clientInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + isProfileableByShell |= clientInfo.isProfileableByShell(); + isProfileable |= clientInfo.isProfileable(); + } } if (debuggableFlag) { @@ -1741,10 +1749,10 @@ public final class ProcessList { if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || mService.mSafeMode) { runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } - if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) != 0) { + if (isProfileableByShell) { runtimeFlags |= Zygote.PROFILE_FROM_SHELL; } - if (app.info.isProfileable()) { + if (isProfileable) { runtimeFlags |= Zygote.PROFILEABLE; } if ("1".equals(SystemProperties.get("debug.checkjni"))) { @@ -1812,7 +1820,7 @@ public final class ProcessList { } String invokeWith = null; - if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + if (debuggableFlag) { // Debuggable apps may include a wrapper script with their library directory. String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh"; StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); @@ -1887,24 +1895,6 @@ public final class ProcessList { } } - /** Return true if the client app for the SDK sandbox process is debuggable. */ - private boolean isAppForSdkSandboxDebuggable(ProcessRecord sandboxProcess) { - // TODO (b/221004701) use client app process name - final int appUid = Process.getAppUidForSdkSandboxUid(sandboxProcess.uid); - IPackageManager pm = mService.getPackageManager(); - try { - String[] packages = pm.getPackagesForUid(appUid); - for (String aPackage : packages) { - ApplicationInfo i = pm.getApplicationInfo(aPackage, 0, sandboxProcess.userId); - if ((i.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { - return true; - } - } - } catch (RemoteException e) { - // shouldn't happen - } - return false; - } @GuardedBy("mService") boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, @@ -2365,7 +2355,7 @@ public final class ProcessList { ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid, - boolean isSdkSandbox, int sdkSandboxUid, + boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { long startTime = SystemClock.uptimeMillis(); ProcessRecord app; @@ -2460,7 +2450,7 @@ public final class ProcessList { if (app == null) { checkSlow(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid, isSdkSandbox, - sdkSandboxUid, hostingRecord); + sdkSandboxUid, sdkSandboxClientAppPackage, hostingRecord); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); @@ -2956,7 +2946,7 @@ public final class ProcessList { @GuardedBy("mService") ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid, boolean isSdkSandbox, int sdkSandboxUid, - HostingRecord hostingRecord) { + String sdkSandboxClientAppPackage, HostingRecord hostingRecord) { String proc = customProcess != null ? customProcess : info.processName; final int userId = UserHandle.getUserId(info.uid); int uid = info.uid; @@ -2992,6 +2982,7 @@ public final class ProcessList { FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED); } final ProcessRecord r = new ProcessRecord(mService, info, proc, uid, + sdkSandboxClientAppPackage, hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName()); final ProcessStateRecord state = r.mState; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index f7cc3d780f89..b4ff8709a32f 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -27,6 +27,7 @@ import android.app.ApplicationExitInfo.Reason; import android.app.ApplicationExitInfo.SubReason; import android.app.IApplicationThread; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManagerInternal; import android.content.pm.ProcessInfo; import android.content.pm.VersionedPackage; import android.content.res.CompatibilityInfo; @@ -84,6 +85,8 @@ class ProcessRecord implements WindowProcessListener { final int uid; // uid of process; may be different from 'info' if isolated final int userId; // user of process. final String processName; // name of the process + final String sdkSandboxClientAppPackage; // if this is an sdk sandbox process, name of the + // app package for which it is running /** * Overall state of process's uid. @@ -493,11 +496,12 @@ class ProcessRecord implements WindowProcessListener { ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName, int _uid) { - this(_service, _info, _processName, _uid, -1, null); + this(_service, _info, _processName, _uid, null, -1, null); } ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName, - int _uid, int _definingUid, String _definingProcessName) { + int _uid, String _sdkSandboxClientAppPackage, int _definingUid, + String _definingProcessName) { mService = _service; mProcLock = _service.mProcLock; info = _info; @@ -530,6 +534,7 @@ class ProcessRecord implements WindowProcessListener { uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; + sdkSandboxClientAppPackage = _sdkSandboxClientAppPackage; mPersistent = false; mRemoved = false; mProfile = new ProcessProfileRecord(this); @@ -861,6 +866,29 @@ class ProcessRecord implements WindowProcessListener { return mDebugging; } + @Nullable + public ApplicationInfo getClientInfoForSdkSandbox() { + if (!isSdkSandbox || sdkSandboxClientAppPackage == null) { + throw new IllegalStateException( + "getClientInfoForSdkSandbox called for non-sandbox process" + ); + } + PackageManagerInternal pm = mService.getPackageManagerInternal(); + return pm.getApplicationInfo( + sdkSandboxClientAppPackage, /* flags */0, Process.SYSTEM_UID, userId); + } + + public boolean isDebuggable() { + if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + return true; + } + if (isSdkSandbox) { + ApplicationInfo clientInfo = getClientInfoForSdkSandbox(); + return clientInfo != null && (clientInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + } + return false; + } + @GuardedBy("mService") void setDebugging(boolean debugging) { mDebugging = debugging; diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index c53d4d6b5015..795311f019a4 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -96,6 +96,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN final long createRealTime; // when this service was created final boolean isSdkSandbox; // whether this is a sdk sandbox service final int sdkSandboxClientAppUid; // the app uid for which this sdk sandbox service is running + final String sdkSandboxClientAppPackage; // the app package for which this sdk sandbox service + // is running final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings = new ArrayMap<Intent.FilterComparison, IntentBindRecord>(); // All active bindings to the service. @@ -573,13 +575,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg, Runnable restarter) { this(ams, name, instanceName, definingPackageName, definingUid, intent, sInfo, callerIsFg, - restarter, null, 0); + restarter, null, 0, null); } ServiceRecord(ActivityManagerService ams, ComponentName name, ComponentName instanceName, String definingPackageName, int definingUid, Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg, - Runnable restarter, String sdkSandboxProcessName, int sdkSandboxClientAppUid) { + Runnable restarter, String sdkSandboxProcessName, int sdkSandboxClientAppUid, + String sdkSandboxClientAppPackage) { this.ams = ams; this.name = name; this.instanceName = instanceName; @@ -590,8 +593,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN serviceInfo = sInfo; appInfo = sInfo.applicationInfo; packageName = sInfo.applicationInfo.packageName; - isSdkSandbox = sdkSandboxProcessName != null; + this.isSdkSandbox = sdkSandboxProcessName != null; this.sdkSandboxClientAppUid = sdkSandboxClientAppUid; + this.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage; if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0) { processName = sInfo.processName + ":" + instanceName.getClassName(); } else if (sdkSandboxProcessName != null) { 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/ambientcontext/AmbientContextManagerPerUserService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java index b73cf5b20ec0..42a7423725a3 100644 --- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java +++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java @@ -171,16 +171,15 @@ final class AmbientContextManagerPerUserService extends return; } - // Remove any existing intent and unregister for this package before adding a new one. + // Remove any existing PendingIntent for this package. String callingPackage = pendingIntent.getCreatorPackage(); PendingIntent duplicatePendingIntent = findExistingRequestByPackage(callingPackage); if (duplicatePendingIntent != null) { - Slog.d(TAG, "Unregister duplicate request from " + callingPackage); - onUnregisterObserver(callingPackage); + Slog.d(TAG, "Replace duplicate request from " + callingPackage); mExistingPendingIntents.remove(duplicatePendingIntent); } - // Register new package and add request to mExistingRequests + // Register package and add pendingIntent to mExistingPendingIntents startDetection(request, callingPackage, createDetectionResultRemoteCallback(), getServerStatusCallback(clientStatusCallback)); mExistingPendingIntents.add(pendingIntent); diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java index 010bf1b4cfb8..e2b22dc1bd3d 100644 --- a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java +++ b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java @@ -110,6 +110,8 @@ final class AmbientContextShellCommand extends ShellCommand { return runStopDetection(); case "get-last-status-code": return getLastStatusCode(); + case "get-last-package-name": + return getLastPackageName(); case "query-service-status": return runQueryServiceStatus(); case "get-bound-package": @@ -157,6 +159,13 @@ final class AmbientContextShellCommand extends ShellCommand { return lastResponse.getStatusCode(); } + private int getLastPackageName() { + AmbientContextDetectionServiceStatus lastResponse = + sTestableCallbackInternal.getLastStatus(); + out.println(lastResponse == null ? "" : lastResponse.getPackageName()); + return 0; + } + @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); @@ -167,6 +176,7 @@ final class AmbientContextShellCommand extends ShellCommand { pw.println(" start-detection USER_ID PACKAGE_NAME: Starts AmbientContextEvent detection."); pw.println(" stop-detection USER_ID: Stops AmbientContextEvent detection."); pw.println(" get-last-status-code: Prints the latest request status code."); + pw.println(" get-last-package-name: Prints the latest request package name."); pw.println(" query-event-status USER_ID PACKAGE_NAME: Prints the event status code."); pw.println(" get-bound-package USER_ID:" + " Print the bound package that implements the service."); diff --git a/services/core/java/com/android/server/ambientcontext/RemoteAmbientContextDetectionService.java b/services/core/java/com/android/server/ambientcontext/RemoteAmbientContextDetectionService.java index f42080d550b7..8aec75226958 100644 --- a/services/core/java/com/android/server/ambientcontext/RemoteAmbientContextDetectionService.java +++ b/services/core/java/com/android/server/ambientcontext/RemoteAmbientContextDetectionService.java @@ -49,6 +49,12 @@ final class RemoteAmbientContextDetectionService connect(); } + @Override + protected long getAutoDisconnectTimeoutMs() { + // Disable automatic unbinding. + return -1; + } + /** * Asks the implementation to start detection. * diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index 193cc5f679af..5af73c9e46ea 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -275,6 +275,7 @@ public class SpatializerHelper { */ synchronized void reset(boolean featureEnabled) { Log.i(TAG, "Resetting"); + releaseSpat(); mState = STATE_UNINITIALIZED; mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; @@ -831,10 +832,10 @@ public class SpatializerHelper { try { mSpat.registerHeadTrackingCallback(null); mSpat.release(); - mSpat = null; } catch (RemoteException e) { Log.e(TAG, "Can't set release spatializer cleanly", e); } + mSpat = null; } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index 7765ab3b8e53..9ae6750dbcbf 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -136,8 +136,8 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession> try { if (mSensorPrivacyManager != null && mSensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, - getTargetUserId())) { + .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, + SensorPrivacyManager.Sensors.CAMERA)) { onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); mCallback.onClientFinished(this, false /* success */); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java index efedcf815228..ded18100e458 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java @@ -96,7 +96,8 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements protected void startHalOperation() { if (mSensorPrivacyManager != null && mSensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) { + .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, + SensorPrivacyManager.Sensors.CAMERA)) { onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); mCallback.onClientFinished(this, false /* success */); return; diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index 8d76e9f031f7..1935a5b135d7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -109,7 +109,8 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { if (mSensorPrivacyManager != null && mSensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) { + .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, + SensorPrivacyManager.Sensors.CAMERA)) { onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); mCallback.onClientFinished(this, false /* success */); return; diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 22d32a665611..50f5536d9f4b 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -467,7 +467,9 @@ public final class DreamManagerService extends SystemService { } mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; - mAtmInternal.notifyDreamStateChanged(false); + mHandler.post(() -> { + mAtmInternal.notifyDreamStateChanged(false); + }); } private void checkPermission(String permission) { diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index cd2ba393f6f2..8407a117be94 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -1184,6 +1184,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mAlarmManager.cancel(mBatchingAlarm); mBatchingAlarm = null; } + mGnssNative.flushBatch(); mGnssNative.stopBatch(); mBatchingStarted = false; } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 3db11d84cbeb..436cc69c9cc8 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -252,8 +252,6 @@ public class LockSettingsService extends ILockSettings.Stub { private final RebootEscrowManager mRebootEscrowManager; - private boolean mFirstCallToVold; - // Current password metric for all users on the device. Updated when user unlocks // the device or changes password. Removed when user is stopped. @GuardedBy("this") @@ -373,7 +371,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 @@ -597,8 +595,6 @@ public class LockSettingsService extends ILockSettings.Stub { mStrongAuth = injector.getStrongAuth(); mActivityManager = injector.getActivityManager(); - mFirstCallToVold = true; - IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_STARTING); @@ -789,7 +785,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 +806,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 +1073,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 +1467,7 @@ public class LockSettingsService extends ILockSettings.Stub { Thread.currentThread().interrupt(); } - if (isCredentialSharedWithParent(userId)) { + if (isCredentialSharableWithParent(userId)) { if (!hasUnifiedChallenge(userId)) { mBiometricDeferredQueue.processPendingLockoutResets(); } @@ -1480,7 +1476,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 +1513,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 +1521,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 +1556,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 +1565,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 +1592,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 +1715,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 +1730,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 +1906,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 +2157,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 { @@ -2474,77 +2470,6 @@ public class LockSettingsService extends ILockSettings.Stub { }); } - private LockscreenCredential createPattern(String patternString) { - final byte[] patternBytes = patternString.getBytes(); - LockscreenCredential pattern = LockscreenCredential.createPattern( - LockPatternUtils.byteArrayToPattern(patternBytes)); - Arrays.fill(patternBytes, (byte) 0); - return pattern; - } - - @Override - public boolean checkVoldPassword(int userId) { - if (!mFirstCallToVold) { - return false; - } - mFirstCallToVold = false; - - checkPasswordReadPermission(); - - // There's no guarantee that this will safely connect, but if it fails - // we will simply show the lock screen when we shouldn't, so relatively - // benign. There is an outside chance something nasty would happen if - // this service restarted before vold stales out the password in this - // case. The nastiness is limited to not showing the lock screen when - // we should, within the first minute of decrypting the phone if this - // service can't connect to vold, it restarts, and then the new instance - // does successfully connect. - final IStorageManager service = mInjector.getStorageManager(); - // TODO(b/120484642): Update vold to return a password as a byte array - String password; - final long identity = Binder.clearCallingIdentity(); - try { - password = service.getPassword(); - service.clearPassword(); - } catch (RemoteException e) { - Slog.w(TAG, "vold getPassword() failed", e); - return false; - } finally { - Binder.restoreCallingIdentity(identity); - } - if (TextUtils.isEmpty(password)) { - return false; - } - - try { - final LockscreenCredential credential; - switch (getCredentialTypeInternal(userId)) { - case CREDENTIAL_TYPE_PATTERN: - credential = createPattern(password); - break; - case CREDENTIAL_TYPE_PIN: - credential = LockscreenCredential.createPin(password); - break; - case CREDENTIAL_TYPE_PASSWORD: - credential = LockscreenCredential.createPassword(password); - break; - default: - credential = null; - Slog.e(TAG, "Unknown credential type"); - } - - if (credential != null - && checkCredential(credential, userId, null /* progressCallback */) - .getResponseCode() == GateKeeperResponse.RESPONSE_OK) { - return true; - } - } catch (Exception e) { - Slog.e(TAG, "checkVoldPassword failed: ", e); - } - - return false; - } - private void removeUser(int userId, boolean unknownUser) { Slog.i(TAG, "RemoveUser: " + userId); removeBiometricsForUser(userId); @@ -2555,7 +2480,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 +3200,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/logcat/LogAccessDialogActivity.java b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java index 7116ca30c5a9..8be90e0cc622 100644 --- a/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java +++ b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; @@ -56,7 +57,7 @@ public class LogAccessDialogActivity extends Activity implements private AlertDialog.Builder mAlertDialog; private AlertDialog mAlert; - private static final int DIALOG_TIME_OUT = 300000; + private static final int DIALOG_TIME_OUT = Build.IS_DEBUGGABLE ? 60000 : 300000; private static final int MSG_DISMISS_DIALOG = 0; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 265ad7dee388..1885b5596e3e 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -630,6 +630,7 @@ public class NotificationManagerService extends SystemService { private int mWarnRemoteViewsSizeBytes; private int mStripRemoteViewsSizeBytes; final boolean mEnableAppSettingMigration; + private boolean mForceUserSetOnUpgrade; private MetricsLogger mMetricsLogger; private TriPredicate<String, Integer, String> mAllowedManagedServicePackages; @@ -2294,6 +2295,7 @@ public class NotificationManagerService extends SystemService { mMsgPkgsAllowedAsConvos = Set.of(getStringArrayResource( com.android.internal.R.array.config_notificationMsgPkgsAllowedAsConvos)); + mStatsManager = statsManager; mToastRateLimiter = toastRateLimiter; @@ -2386,6 +2388,9 @@ public class NotificationManagerService extends SystemService { WorkerHandler handler = new WorkerHandler(Looper.myLooper()); + mForceUserSetOnUpgrade = getContext().getResources().getBoolean( + R.bool.config_notificationForceUserSetOnUpgrade); + init(handler, new RankingHandlerWorker(mRankingThread.getLooper()), AppGlobals.getPackageManager(), getContext().getPackageManager(), getLocalService(LightsManager.class), @@ -2414,7 +2419,8 @@ public class NotificationManagerService extends SystemService { LocalServices.getService(ActivityManagerInternal.class), createToastRateLimiter(), new PermissionHelper(LocalServices.getService( PermissionManagerServiceInternal.class), AppGlobals.getPackageManager(), - AppGlobals.getPermissionManager(), mEnableAppSettingMigration), + AppGlobals.getPermissionManager(), mEnableAppSettingMigration, + mForceUserSetOnUpgrade), LocalServices.getService(UsageStatsManagerInternal.class)); publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false, @@ -6069,6 +6075,7 @@ public class NotificationManagerService extends SystemService { pw.println(" mMaxPackageEnqueueRate=" + mMaxPackageEnqueueRate); pw.println(" hideSilentStatusBar=" + mPreferencesHelper.shouldHideSilentStatusIcons()); + pw.println(" mForceUserSetOnUpgrade=" + mForceUserSetOnUpgrade); } pw.println(" mArchive=" + mArchive.toString()); mArchive.dumpImpl(pw, filter); diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java index e551f1056b24..b4230c11bcab 100644 --- a/services/core/java/com/android/server/notification/PermissionHelper.java +++ b/services/core/java/com/android/server/notification/PermissionHelper.java @@ -57,13 +57,16 @@ public final class PermissionHelper { private final IPermissionManager mPermManager; // TODO (b/194833441): Remove when the migration is enabled private final boolean mMigrationEnabled; + private final boolean mForceUserSetOnUpgrade; public PermissionHelper(PermissionManagerServiceInternal pmi, IPackageManager packageManager, - IPermissionManager permManager, boolean migrationEnabled) { + IPermissionManager permManager, boolean migrationEnabled, + boolean forceUserSetOnUpgrade) { mPmi = pmi; mPackageManager = packageManager; mPermManager = permManager; mMigrationEnabled = migrationEnabled; + mForceUserSetOnUpgrade = forceUserSetOnUpgrade; } public boolean isMigrationEnabled() { @@ -223,8 +226,9 @@ public final class PermissionHelper { return; } if (!isPermissionFixed(pkgPerm.packageName, pkgPerm.userId)) { + boolean userSet = mForceUserSetOnUpgrade ? true : pkgPerm.userModifiedSettings; setNotificationPermission(pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted, - pkgPerm.userSet, !pkgPerm.userSet); + userSet, !userSet); } } @@ -305,13 +309,13 @@ public final class PermissionHelper { public final String packageName; public final @UserIdInt int userId; public final boolean granted; - public final boolean userSet; + public final boolean userModifiedSettings; public PackagePermission(String pkg, int userId, boolean granted, boolean userSet) { this.packageName = pkg; this.userId = userId; this.granted = granted; - this.userSet = userSet; + this.userModifiedSettings = userSet; } @Override @@ -319,13 +323,14 @@ public final class PermissionHelper { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PackagePermission that = (PackagePermission) o; - return userId == that.userId && granted == that.granted && userSet == that.userSet + return userId == that.userId && granted == that.granted && userModifiedSettings + == that.userModifiedSettings && Objects.equals(packageName, that.packageName); } @Override public int hashCode() { - return Objects.hash(packageName, userId, granted, userSet); + return Objects.hash(packageName, userId, granted, userModifiedSettings); } @Override @@ -334,7 +339,7 @@ public final class PermissionHelper { "packageName='" + packageName + '\'' + ", userId=" + userId + ", granted=" + granted + - ", userSet=" + userSet + + ", userSet=" + userModifiedSettings + '}'; } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 93f1b4741bd6..9e0c97502c4f 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -104,6 +104,7 @@ public class ZenModeHelper { // The amount of time rules instances can exist without their owning app being installed. private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72; + static final int RULE_LIMIT_PER_PACKAGE = 100; // pkg|userId => uid protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>(); @@ -329,10 +330,10 @@ public class ZenModeHelper { int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner()) + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity()) + 1; - if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) { + if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE + || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) { throw new IllegalArgumentException("Rule instance limit exceeded"); } - } ZenModeConfig newConfig; 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 index bbef237507bf..b41a0b8878e0 100644 --- a/services/core/java/com/android/server/pm/AppIdSettingMap.java +++ b/services/core/java/com/android/server/pm/AppIdSettingMap.java @@ -17,46 +17,131 @@ package com.android.server.pm; import android.os.Process; +import android.util.Log; +import com.android.server.utils.WatchedArrayList; import com.android.server.utils.WatchedSparseArray; +import com.android.server.utils.Watcher; /** - * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID. + * A wrapper over {@link WatchedArrayList} that tracks the current (app ID -> SettingBase) mapping + * for non-system apps. Also tracks system app settings in an {@link WatchedSparseArray}. */ -public class AppIdSettingMap extends WatchedSparseArray<SettingBase> { - private int mCurrentMaxAppId; +final class AppIdSettingMap { + /** + * We use an ArrayList instead of an SparseArray for non system apps because the number of apps + * might be big, and only ArrayList gives us a constant lookup time. For a given app ID, the + * index to the corresponding SettingBase object is (appId - FIRST_APPLICATION_ID). If an app ID + * doesn't exist (i.e., app is not installed), we fill the corresponding entry with null. + */ + private WatchedArrayList<SettingBase> mNonSystemSettings = new WatchedArrayList<>(); + private WatchedSparseArray<SettingBase> mSystemSettings = new WatchedSparseArray<>(); + private int mFirstAvailableAppId = Process.FIRST_APPLICATION_UID; - @Override - public void put(int key, SettingBase value) { - if (key > mCurrentMaxAppId) { - mCurrentMaxAppId = key; + /** Returns true if the requested AppID was valid and not already registered. */ + public boolean registerExistingAppId(int appId, SettingBase setting, Object name) { + if (appId >= Process.FIRST_APPLICATION_UID) { + int size = mNonSystemSettings.size(); + final int index = appId - Process.FIRST_APPLICATION_UID; + // fill the array until our index becomes valid + while (index >= size) { + mNonSystemSettings.add(null); + size++; + } + if (mNonSystemSettings.get(index) != null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Adding duplicate app id: " + appId + + " name=" + name); + return false; + } + mNonSystemSettings.set(index, setting); + } else { + if (mSystemSettings.get(appId) != null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Adding duplicate shared id: " + appId + + " name=" + name); + return false; + } + mSystemSettings.put(appId, setting); } - super.put(key, value); + return true; } - @Override - public AppIdSettingMap snapshot() { - AppIdSettingMap l = new AppIdSettingMap(); - snapshot(l, this); - return l; + public SettingBase getSetting(int appId) { + if (appId >= Process.FIRST_APPLICATION_UID) { + final int size = mNonSystemSettings.size(); + final int index = appId - Process.FIRST_APPLICATION_UID; + return index < size ? mNonSystemSettings.get(index) : null; + } else { + return mSystemSettings.get(appId); + } } - /** - * @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; + public void removeSetting(int appId) { + if (appId >= Process.FIRST_APPLICATION_UID) { + final int size = mNonSystemSettings.size(); + final int index = appId - Process.FIRST_APPLICATION_UID; + if (index < size) { + mNonSystemSettings.set(index, null); + } + } else { + mSystemSettings.remove(appId); + } + setFirstAvailableAppId(appId + 1); } - /** - * @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; + // This should be called (at least) whenever an application is removed + private void setFirstAvailableAppId(int uid) { + if (uid > mFirstAvailableAppId) { + mFirstAvailableAppId = uid; + } + } + + public void replaceSetting(int appId, SettingBase setting) { + if (appId >= Process.FIRST_APPLICATION_UID) { + final int size = mNonSystemSettings.size(); + final int index = appId - Process.FIRST_APPLICATION_UID; + if (index < size) { + mNonSystemSettings.set(index, setting); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: calling replaceAppIdLpw to" + + " replace SettingBase at appId=" + appId + + " but nothing is replaced."); + } } else { - return mCurrentMaxAppId + 1; + mSystemSettings.put(appId, setting); + } + } + + /** Returns a new AppID or -1 if we could not find an available AppID to assign */ + public int acquireAndRegisterNewAppId(SettingBase obj) { + final int size = mNonSystemSettings.size(); + for (int i = mFirstAvailableAppId - Process.FIRST_APPLICATION_UID; i < size; i++) { + if (mNonSystemSettings.get(i) == null) { + mNonSystemSettings.set(i, obj); + return Process.FIRST_APPLICATION_UID + i; + } + } + + // None left? + if (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) { + return -1; } + + mNonSystemSettings.add(obj); + return Process.FIRST_APPLICATION_UID + size; + } + + public AppIdSettingMap snapshot() { + AppIdSettingMap l = new AppIdSettingMap(); + mNonSystemSettings.snapshot(l.mNonSystemSettings, mNonSystemSettings); + mSystemSettings.snapshot(l.mSystemSettings, mSystemSettings); + return l; + } + + public void registerObserver(Watcher observer) { + mNonSystemSettings.registerObserver(observer); + mSystemSettings.registerObserver(observer); } } 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/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index b30798485bf7..89f8be27096a 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -112,7 +112,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { String callingFeatureId, ComponentName component, @UserIdInt int userId, - boolean launchMainActivity) throws RemoteException { + boolean launchMainActivity, + IBinder targetTask, + Bundle options) throws RemoteException { Objects.requireNonNull(callingPackage); Objects.requireNonNull(component); @@ -145,8 +147,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (launchMainActivity) { launchIntent.setAction(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + if (targetTask == null) { + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + } else { + launchIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + } // Only package name is set here, as opposed to component name, because intent action // and category are ignored if component name is present while we are resolving intent. launchIntent.setPackage(component.getPackageName()); @@ -170,15 +176,20 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } verifyActivityCanHandleIntentAndExported(launchIntent, component, callingUid, userId); + // Always show the cross profile animation + if (options == null) { + options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(); + } else { + options.putAll(ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle()); + } + launchIntent.setPackage(null); launchIntent.setComponent(component); mInjector.getActivityTaskManagerInternal().startActivityAsUser( caller, callingPackage, callingFeatureId, launchIntent, - /* resultTo= */ null, - Intent.FLAG_ACTIVITY_NEW_TASK, - launchMainActivity - ? ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle() - : null, + targetTask, + /* startFlags= */ 0, + options, userId); } @@ -225,6 +236,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { verifyActivityCanHandleIntent(launchIntent, callingUid, userId); + // Always show the cross profile animation + if (options == null) { + options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(); + } else { + options.putAll(ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle()); + } + mInjector.getActivityTaskManagerInternal() .startActivityAsUser( caller, 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..91750dee7688 100644 --- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java +++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java @@ -30,6 +30,7 @@ import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX; import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN; import static com.android.server.pm.PackageManagerService.SYSTEM_PARTITIONS; import static com.android.server.pm.PackageManagerService.TAG; +import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.PARSE_CHECK_MAX_SDK_VERSION; import android.annotation.Nullable; import android.content.pm.parsing.ApkLiteParseUtils; @@ -170,7 +171,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. @@ -313,10 +314,14 @@ final class InitAndSystemPackageHelper { @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) private void scanDirTracedLI(File scanDir, List<File> frameworkSplits, - final int parseFlags, int scanFlags, + int parseFlags, int scanFlags, long currentTime, PackageParser2 packageParser, ExecutorService executorService) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]"); try { + if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { + // when scanning apk in apexes, we want to check the maxSdkVersion + parseFlags |= PARSE_CHECK_MAX_SDK_VERSION; + } mInstallPackageHelper.installPackagesFromDir(scanDir, frameworkSplits, parseFlags, scanFlags, currentTime, packageParser, executorService); } finally { 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/OWNERS b/services/core/java/com/android/server/pm/OWNERS index c219f80ac9c5..8534fabb5576 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -15,7 +15,9 @@ per-file StagingManager.java = dariofreni@google.com, ioffe@google.com, olilan@g per-file AbstractStatsBase.java = file:dex/OWNERS per-file BackgroundDexOptService.java = file:dex/OWNERS per-file CompilerStats.java = file:dex/OWNERS +per-file DexOptHelper.java = file:dex/OWNERS per-file DynamicCodeLoggingService.java = file:dex/OWNERS +per-file Installer.java = file:dex/OWNERS per-file InstructionSets.java = file:dex/OWNERS per-file OtaDexoptService.java = file:dex/OWNERS per-file OtaDexoptShellCommand.java = file:dex/OWNERS 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..67056ead3423 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 { - - @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*/); - } + public class IPackageManagerImpl extends IPackageManagerBase { - @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,19 +5062,7 @@ 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) { + public void makeProviderVisible(int recipientUid, @NonNull String visibleAuthority) { final Computer snapshot = snapshotComputer(); final int recipientUserId = UserHandle.getUserId(recipientUid); final ProviderInfo providerInfo = @@ -5864,36 +5076,24 @@ 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; - } + public void makeUidVisible(int recipientUid, int visibleUid) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MAKE_UID_VISIBLE, "makeUidVisible"); + final int callingUid = Binder.getCallingUid(); + final int recipientUserId = UserHandle.getUserId(recipientUid); + final int visibleUserId = UserHandle.getUserId(visibleUid); + final Computer snapshot = snapshotComputer(); + snapshot.enforceCrossUserPermission(callingUid, recipientUserId, + false /* requireFullPermission */, false /* checkShell */, "makeUidVisible"); + snapshot.enforceCrossUserPermission(callingUid, visibleUserId, + false /* requireFullPermission */, false /* checkShell */, "makeUidVisible"); + snapshot.enforceCrossUserPermission(recipientUid, visibleUserId, + false /* requireFullPermission */, false /* checkShell */, "makeUidVisible"); - @Override - public boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate, - @PackageManager.CertificateInputType int type) { - return mComputer.hasUidSigningCertificate(uid, certificate, type); + PackageManagerService.this.grantImplicitAccess(snapshot, recipientUserId, + null /*Intent*/, UserHandle.getAppId(recipientUid), visibleUid, + false /*direct*/, false /* retainOnUpdate */); } @Override @@ -5924,55 +5124,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 +5143,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 +5159,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 +5166,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 +5226,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 +5262,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 +5286,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 +5305,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 +5312,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 +5323,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 +5341,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 +5358,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 +5385,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 +5400,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 +5462,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 +5480,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 +5521,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 +5545,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 +5604,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 +5617,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 +5669,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 +5690,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 +5711,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 +5738,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 +5766,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 +5822,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } } - targetPackageState = getPackageStateInternal(targetPackage); + targetPackageState = snapshotComputer().getPackageStateInternal(targetPackage); mSettings.addInstallerPackageNames(targetPackageState.getInstallSource()); } mAppsFilter.addPackage(targetPackageState); @@ -6818,14 +5836,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 +5859,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 +5902,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 +5937,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 +5953,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 +5966,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 +5986,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 +6001,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 +6018,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 +6034,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); - } - - @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); - } + private class PackageManagerInternalImpl extends PackageManagerInternalBase { - @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 +6167,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 +6177,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 +6194,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 +6203,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 +6210,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 +6228,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 +6235,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 +6248,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 +6256,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 +6268,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 +6289,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 +6307,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 +6321,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 +6342,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 +6351,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 +6425,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 +6438,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 +6448,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 +6456,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 +6481,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 +6491,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 +6622,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 +6637,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 +6647,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 +6673,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 +6681,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService action.accept(packageState.getPkg()); } }; - forEachPackageState(mComputer.getPackageStates(), actionWrapped); + forEachPackageState(snapshot.getPackageStates(), actionWrapped); } boolean isHistoricalPackageUsageAvailable() { @@ -8345,15 +6696,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 +6727,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 +6736,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 +6745,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 +6812,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 +6835,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 +6886,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 +6896,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 +6943,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 +7000,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDefaultAppProvider.setDefaultBrowser(packageName, async, userId); } - ResolveInfo getInstantAppInstallerInfo() { - return mInstantAppInstallerInfo; - } - PackageUsage getPackageUsage() { return mPackageUsage; } @@ -8754,10 +7091,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/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 62e9d372f09d..15753cd24e85 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -2540,8 +2540,10 @@ class PackageManagerShellCommand extends ShellCommand { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppPermissions(pkg); } else if (isApexApp(pkg)) { + final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName( + getApexPackageNameContainingPackage(pkg)); privAppPermissions = SystemConfig.getInstance() - .getApexPrivAppPermissions(getApexPackageNameContainingPackage(pkg), pkg); + .getApexPrivAppPermissions(apexName, pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); } @@ -2567,8 +2569,10 @@ class PackageManagerShellCommand extends ShellCommand { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppDenyPermissions(pkg); } else if (isApexApp(pkg)) { + final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName( + getApexPackageNameContainingPackage(pkg)); privAppPermissions = SystemConfig.getInstance() - .getApexPrivAppDenyPermissions(getApexPackageNameContainingPackage(pkg), pkg); + .getApexPrivAppDenyPermissions(apexName, pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); } 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 6ccaae148ce6..698dbe945e6f 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -62,7 +62,6 @@ import android.os.Handler; import android.os.Message; import android.os.PatternMatcher; import android.os.PersistableBundle; -import android.os.Process; import android.os.SELinux; import android.os.SystemClock; import android.os.Trace; @@ -408,8 +407,6 @@ public final class Settings implements Watchable, Snappable { int[] excludedUserIds; } - private static int mFirstAvailableUid = Process.FIRST_APPLICATION_UID; - /** Map from volume UUID to {@link VersionInfo} */ @Watched private final WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>(); @@ -472,10 +469,8 @@ public final class Settings implements Watchable, Snappable { @Watched final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>(); - @Watched + @Watched(manual = true) private final AppIdSettingMap mAppIds; - @Watched - private final AppIdSettingMap mOtherAppIds; // For reading/writing settings file. @Watched @@ -565,7 +560,6 @@ public final class Settings implements Watchable, Snappable { mCrossProfileIntentResolvers.registerObserver(mObserver); mSharedUsers.registerObserver(mObserver); mAppIds.registerObserver(mObserver); - mOtherAppIds.registerObserver(mObserver); mRenamedPackages.registerObserver(mObserver); mNextAppLinkGeneration.registerObserver(mObserver); mDefaultBrowserApp.registerObserver(mObserver); @@ -592,7 +586,6 @@ public final class Settings implements Watchable, Snappable { mLock = new PackageManagerTracedLock(); mPackages.putAll(pkgSettings); mAppIds = new AppIdSettingMap(); - mOtherAppIds = new AppIdSettingMap(); mSystemDir = null; mPermissions = null; mRuntimePermissionsPersistence = null; @@ -629,7 +622,6 @@ public final class Settings implements Watchable, Snappable { mLock = lock; mAppIds = new AppIdSettingMap(); - mOtherAppIds = new AppIdSettingMap(); mPermissions = new LegacyPermissionSettings(lock); mRuntimePermissionsPersistence = new RuntimePermissionPersistence( runtimePermissionsPersistence, new Consumer<Integer>() { @@ -710,7 +702,6 @@ public final class Settings implements Watchable, Snappable { mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers); mSharedUsers.snapshot(r.mSharedUsers); mAppIds = r.mAppIds.snapshot(); - mOtherAppIds = r.mOtherAppIds.snapshot(); WatchedArrayList.snapshot( mPastSignatures, r.mPastSignatures); WatchedArrayMap.snapshot( @@ -782,7 +773,7 @@ public final class Settings implements Watchable, Snappable { SharedUserSetting s = mSharedUsers.get(name); if (s == null && create) { s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags); - s.mAppId = acquireAndRegisterNewAppIdLPw(s); + s.mAppId = mAppIds.acquireAndRegisterNewAppId(s); if (s.mAppId < 0) { // < 0 means we couldn't assign a userid; throw exception throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, @@ -890,7 +881,7 @@ public final class Settings implements Watchable, Snappable { pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions, usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId); p.setAppId(uid); - if (registerExistingAppIdLPw(uid, p, name)) { + if (mAppIds.registerExistingAppId(uid, p, name)) { mPackages.put(name, p); return p; } @@ -909,7 +900,7 @@ public final class Settings implements Watchable, Snappable { } s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags); s.mAppId = uid; - if (registerExistingAppIdLPw(uid, s, name)) { + if (mAppIds.registerExistingAppId(uid, s, name)) { mSharedUsers.put(name, s); return s; } @@ -1210,11 +1201,11 @@ public final class Settings implements Watchable, Snappable { final boolean createdNew; if (p.getAppId() == 0 || forceNew) { // Assign new user ID - p.setAppId(acquireAndRegisterNewAppIdLPw(p)); + p.setAppId(mAppIds.acquireAndRegisterNewAppId(p)); createdNew = true; } else { // Add new setting to list of user IDs - createdNew = registerExistingAppIdLPw(p.getAppId(), p, p.getPackageName()); + createdNew = mAppIds.registerExistingAppId(p.getAppId(), p, p.getPackageName()); } if (p.getAppId() < 0) { PackageManagerService.reportSettingsProblem(Log.WARN, @@ -1304,11 +1295,11 @@ public final class Settings implements Watchable, Snappable { Object userIdPs = getSettingLPr(p.getAppId()); if (sharedUser == null) { if (userIdPs != null && userIdPs != p) { - replaceAppIdLPw(p.getAppId(), p); + mAppIds.replaceSetting(p.getAppId(), p); } } else { if (userIdPs != null && userIdPs != sharedUser) { - replaceAppIdLPw(p.getAppId(), sharedUser); + mAppIds.replaceSetting(p.getAppId(), sharedUser); } } } @@ -1357,73 +1348,22 @@ public final class Settings implements Watchable, Snappable { mInstallerPackages.remove(packageName); } - /** Returns true if the requested AppID was valid and not already registered. */ - private boolean registerExistingAppIdLPw(int appId, SettingBase obj, Object name) { - if (appId > Process.LAST_APPLICATION_UID) { - return false; - } - - if (appId >= Process.FIRST_APPLICATION_UID) { - if (mAppIds.get(appId) != null) { - PackageManagerService.reportSettingsProblem(Log.WARN, - "Adding duplicate app id: " + appId - + " name=" + name); - return false; - } - mAppIds.put(appId, obj); - } else { - if (mOtherAppIds.get(appId) != null) { - PackageManagerService.reportSettingsProblem(Log.WARN, - "Adding duplicate shared id: " + appId - + " name=" + name); - return false; - } - mOtherAppIds.put(appId, obj); - } - return true; - } - /** Gets the setting associated with the provided App ID */ public SettingBase getSettingLPr(int appId) { - if (appId >= Process.FIRST_APPLICATION_UID) { - return mAppIds.get(appId); - } else { - return mOtherAppIds.get(appId); - } + return mAppIds.getSetting(appId); } /** Unregisters the provided app ID. */ void removeAppIdLPw(int appId) { - if (appId >= Process.FIRST_APPLICATION_UID) { - mAppIds.remove(appId); - } else { - mOtherAppIds.remove(appId); - } - setFirstAvailableUid(appId + 1); - } - - private void replaceAppIdLPw(int appId, SettingBase obj) { - if (appId >= Process.FIRST_APPLICATION_UID) { - 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); - } + mAppIds.removeSetting(appId); } - /** * Transparently convert a SharedUserSetting into PackageSettings without changing appId. * The sharedUser passed to this method has to be {@link SharedUserSetting#isSingleUser()}. */ void convertSharedUserSettingsLPw(SharedUserSetting sharedUser) { final PackageSetting ps = sharedUser.getPackageSettings().valueAt(0); - replaceAppIdLPw(sharedUser.getAppId(), ps); + mAppIds.replaceSetting(sharedUser.getAppId(), ps); // Unlink the SharedUserSetting ps.setSharedUserAppId(INVALID_UID); @@ -4287,32 +4227,6 @@ public final class Settings implements Watchable, Snappable { } } - // This should be called (at least) whenever an application is removed - private void setFirstAvailableUid(int uid) { - if (uid > mFirstAvailableUid) { - mFirstAvailableUid = uid; - } - } - - /** Returns a new AppID or -1 if we could not find an available AppID to assign */ - private int acquireAndRegisterNewAppIdLPw(SettingBase obj) { - 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 (nextAvailableAppId > Process.LAST_APPLICATION_UID) { - return -1; - } - - mAppIds.put(nextAvailableAppId, obj); - return nextAvailableAppId; - } - public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) { if (mVerifierDeviceIdentity == null) { mVerifierDeviceIdentity = VerifierDeviceIdentity.generate(); 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/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 1cf2dc52e430..25fe0007ec4b 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -488,7 +488,8 @@ public class ShortcutService extends IShortcutService.Stub { mShortcutBitmapSaver = new ShortcutBitmapSaver(this); mShortcutDumpFiles = new ShortcutDumpFiles(this); mIsAppSearchEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true); + SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true) + && !injectIsLowRamDevice(); if (onlyForPackageManagerApis) { return; // Don't do anything further. For unit tests only. 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/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index 88a298a756d4..9c74dd795d30 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -52,9 +52,6 @@ "options": [ { "include-filter": "com.google.android.security.gts.PackageVerifierTest" - }, - { - "exclude-filter": "com.google.android.security.gts.PackageVerifierTest#testAdbInstall_timeout_allowed" } ] }, diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index a8d24fad2598..34b7ad41e540 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); } @@ -4638,12 +4638,12 @@ public class UserManagerService extends IUserManager.Stub { final String restriction = getUserRemovalRestriction(userId); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) { Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled."); - return UserManager.REMOVE_RESULT_ERROR; + return UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION; } } if (userId == UserHandle.USER_SYSTEM) { Slog.e(LOG_TAG, "System user cannot be removed."); - return UserManager.REMOVE_RESULT_ERROR; + return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER; } final long ident = Binder.clearCallingIdentity(); @@ -4655,7 +4655,7 @@ public class UserManagerService extends IUserManager.Stub { if (userData == null) { Slog.e(LOG_TAG, "Cannot remove user " + userId + ", invalid user id provided."); - return UserManager.REMOVE_RESULT_ERROR; + return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND; } if (mRemovingUserIds.get(userId)) { 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/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/pm/dex/OWNERS b/services/core/java/com/android/server/pm/dex/OWNERS index 052a4ca52afd..5ca8ddd1fe17 100644 --- a/services/core/java/com/android/server/pm/dex/OWNERS +++ b/services/core/java/com/android/server/pm/dex/OWNERS @@ -1,3 +1,4 @@ alanstokes@google.com jiakaiz@google.com ngeoffray@google.com +mast@google.com diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index 90842619c31e..d0609307e6a8 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -3291,10 +3291,13 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } else if (pkg.isSystemExt()) { permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName()); } else if (containingApexPackageName != null) { + final ApexManager apexManager = ApexManager.getInstance(); + final String apexName = apexManager.getApexModuleNameForPackageName( + containingApexPackageName); final Set<String> privAppPermissions = systemConfig.getPrivAppPermissions( pkg.getPackageName()); final Set<String> apexPermissions = systemConfig.getApexPrivAppPermissions( - containingApexPackageName, pkg.getPackageName()); + apexName, pkg.getPackageName()); if (privAppPermissions != null) { // TODO(andreionea): Remove check as soon as all apk-in-apex // permission allowlists are migrated. diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java index cbba346ce7b8..40f859c5e82e 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java @@ -302,6 +302,8 @@ public interface ParsingPackage extends ParsingPackageRead { ParsingPackage setMinSdkVersion(int minSdkVersion); + ParsingPackage setMaxSdkVersion(int maxSdkVersion); + ParsingPackage setNetworkSecurityConfigRes(int networkSecurityConfigRes); ParsingPackage setNonLocalizedLabel(CharSequence nonLocalizedLabel); diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java index 1484df8ece14..67d9aecf01bd 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java @@ -383,6 +383,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, @Nullable private SparseIntArray minExtensionVersions; private int minSdkVersion = ParsingUtils.DEFAULT_MIN_SDK_VERSION; + private int maxSdkVersion = ParsingUtils.DEFAULT_MAX_SDK_VERSION; private int networkSecurityConfigRes; @Nullable private CharSequence nonLocalizedLabel; @@ -1306,6 +1307,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, dest.writeFloat(this.maxAspectRatio); dest.writeFloat(this.minAspectRatio); dest.writeInt(this.minSdkVersion); + dest.writeInt(this.maxSdkVersion); dest.writeInt(this.networkSecurityConfigRes); dest.writeCharSequence(this.nonLocalizedLabel); dest.writeString(this.permission); @@ -1454,6 +1456,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, this.maxAspectRatio = in.readFloat(); this.minAspectRatio = in.readFloat(); this.minSdkVersion = in.readInt(); + this.maxSdkVersion = in.readInt(); this.networkSecurityConfigRes = in.readInt(); this.nonLocalizedLabel = in.readCharSequence(); this.permission = in.readString(); @@ -2068,6 +2071,11 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, } @Override + public int getMaxSdkVersion() { + return maxSdkVersion; + } + + @Override public int getNetworkSecurityConfigRes() { return networkSecurityConfigRes; } @@ -2592,6 +2600,12 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, } @Override + public ParsingPackageImpl setMaxSdkVersion(int value) { + maxSdkVersion = value; + return this; + } + + @Override public ParsingPackageImpl setNetworkSecurityConfigRes(int value) { networkSecurityConfigRes = value; return this; diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java index 112b9e070d28..b3239486a75f 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java @@ -209,6 +209,8 @@ public class ParsingPackageUtils { public static final int SDK_VERSION = Build.VERSION.SDK_INT; public static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; + public static final String[] PREVIOUS_CODENAMES = + Build.VERSION.KNOWN_CODENAMES.toArray(new String[]{}); public static boolean sCompatibilityModeEnabled = true; public static boolean sUseRoundIcon = false; @@ -236,6 +238,7 @@ public class ParsingPackageUtils { */ public static final int PARSE_IGNORE_OVERLAY_REQUIRED_SYSTEM_PROPERTY = 1 << 7; public static final int PARSE_FRAMEWORK_RES_SPLITS = 1 << 8; + public static final int PARSE_CHECK_MAX_SDK_VERSION = 1 << 9; public static final int PARSE_CHATTY = 1 << 31; @@ -1002,7 +1005,7 @@ public class ParsingPackageUtils { case TAG_FEATURE_GROUP: return parseFeatureGroup(input, pkg, res, parser); case TAG_USES_SDK: - return parseUsesSdk(input, pkg, res, parser); + return parseUsesSdk(input, pkg, res, parser, flags); case TAG_SUPPORT_SCREENS: return parseSupportScreens(input, pkg, res, parser); case TAG_PROTECTED_BROADCAST: @@ -1514,15 +1517,17 @@ public class ParsingPackageUtils { } private static ParseResult<ParsingPackage> parseUsesSdk(ParseInput input, - ParsingPackage pkg, Resources res, XmlResourceParser parser) + ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags) throws IOException, XmlPullParserException { if (SDK_VERSION > 0) { + final boolean checkMaxSdkVersion = (flags & PARSE_CHECK_MAX_SDK_VERSION) != 0; TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk); try { int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION; String minCode = null; int targetVers = ParsingUtils.DEFAULT_TARGET_SDK_VERSION; String targetCode = null; + int maxVers = Integer.MAX_VALUE; TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion); if (val != null) { @@ -1550,6 +1555,14 @@ public class ParsingPackageUtils { targetCode = minCode; } + if (checkMaxSdkVersion) { + val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_maxSdkVersion); + if (val != null) { + // maxSdkVersion only supports integer + maxVers = val.data; + } + } + ParseResult<Integer> targetSdkVersionResult = FrameworkParsingPackageUtils .computeTargetSdkVersion(targetVers, targetCode, SDK_CODENAMES, input); if (targetSdkVersionResult.isError()) { @@ -1574,6 +1587,15 @@ public class ParsingPackageUtils { pkg.setMinSdkVersion(minSdkVersion) .setTargetSdkVersion(targetSdkVersion); + if (checkMaxSdkVersion) { + ParseResult<Integer> maxSdkVersionResult = FrameworkParsingPackageUtils + .computeMaxSdkVersion(maxVers, SDK_VERSION, input); + if (maxSdkVersionResult.isError()) { + return input.error(maxSdkVersionResult); + } + int maxSdkVersion = maxSdkVersionResult.getResult(); + pkg.setMaxSdkVersion(maxSdkVersion); + } int type; final int innerDepth = parser.getDepth(); diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java index cb474df8b469..07512855d276 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java @@ -50,6 +50,7 @@ public class ParsingUtils { public static final String ANDROID_RES_NAMESPACE = "http://schemas.android.com/apk/res/android"; public static final int DEFAULT_MIN_SDK_VERSION = 1; + public static final int DEFAULT_MAX_SDK_VERSION = Integer.MAX_VALUE; public static final int DEFAULT_TARGET_SDK_VERSION = 0; public static final int NOT_SET = -1; diff --git a/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java b/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java index 3205b76d6dad..99bcdb964c2f 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java @@ -250,6 +250,11 @@ public interface PkgWithoutStateAppInfo { int getMinSdkVersion(); /** + * @see R.styleable#AndroidManifestUsesSdk_maxSdkVersion + */ + int getMaxSdkVersion(); + + /** * @see ApplicationInfo#getNativeHeapZeroInitialized() * @see R.styleable#AndroidManifestApplication_nativeHeapZeroInitialized */ diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index e79148d52715..dc5b325022a6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -792,7 +792,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void onWakeUp() { synchronized (mLock) { if (shouldEnableWakeGestureLp() - && mBatteryManagerInternal.getPlugType() != BATTERY_PLUGGED_WIRELESS) { + && getBatteryManagerInternal().getPlugType() != BATTERY_PLUGGED_WIRELESS) { performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false, "Wake Up"); wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture, diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java index 990b21c211a3..1cc05391b497 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.media.permission.SafeCloseable; import android.media.soundtrigger.ModelParameterRange; import android.media.soundtrigger.PhraseRecognitionEvent; +import android.media.soundtrigger.PhraseRecognitionExtra; import android.media.soundtrigger.PhraseSoundModel; import android.media.soundtrigger.Properties; import android.media.soundtrigger.RecognitionConfig; @@ -392,7 +393,7 @@ public class SoundTriggerHalConcurrentCaptureHandler implements ISoundTriggerHal private static void notifyAbort(int modelHandle, LoadedModel model) { switch (model.type) { case SoundModelType.GENERIC: { - RecognitionEvent event = new RecognitionEvent(); + RecognitionEvent event = newEmptyRecognitionEvent(); event.status = RecognitionStatus.ABORTED; event.type = SoundModelType.GENERIC; model.callback.recognitionCallback(modelHandle, event); @@ -400,7 +401,7 @@ public class SoundTriggerHalConcurrentCaptureHandler implements ISoundTriggerHal break; case SoundModelType.KEYPHRASE: { - PhraseRecognitionEvent event = new PhraseRecognitionEvent(); + PhraseRecognitionEvent event = newEmptyPhraseRecognitionEvent(); event.common.status = RecognitionStatus.ABORTED; event.common.type = SoundModelType.KEYPHRASE; model.callback.phraseRecognitionCallback(modelHandle, event); @@ -415,6 +416,19 @@ public class SoundTriggerHalConcurrentCaptureHandler implements ISoundTriggerHal mNotifier.unregisterListener(this); } + private static PhraseRecognitionEvent newEmptyPhraseRecognitionEvent() { + PhraseRecognitionEvent result = new PhraseRecognitionEvent(); + result.common = newEmptyRecognitionEvent(); + result.phraseExtras = new PhraseRecognitionExtra[0]; + return result; + } + + private static RecognitionEvent newEmptyRecognitionEvent() { + RecognitionEvent result = new RecognitionEvent(); + result.data = new byte[0]; + return result; + } + //////////////////////////////////////////////////////////////////////////////////////////////// // All methods below do trivial delegation - no interesting logic. @Override diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 59b9daf709d8..80877382f75a 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -36,6 +36,7 @@ import android.app.Notification; import android.app.StatusBarManager; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.Context; @@ -135,6 +136,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) private static final long LOCK_DOWN_COLLAPSE_STATUS_BAR = 173031413L; + /** + * In apps targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher, calling + * {@link android.service.quicksettings.TileService#requestListeningState} will check that the + * calling package (uid) and the package of the target {@link android.content.ComponentName} + * match. It'll also make sure that the context used can take actions on behalf of the current + * user. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) + static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L; + private final Context mContext; private final Handler mHandler = new Handler(); @@ -1652,6 +1664,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void hideCurrentInputMethodForBubbles() { + enforceStatusBarService(); final long token = Binder.clearCallingIdentity(); try { InputMethodManagerInternal.get().hideCurrentInputMethod( @@ -1776,6 +1789,42 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override + public void requestTileServiceListeningState( + @NonNull ComponentName componentName, + int userId + ) { + int callingUid = Binder.getCallingUid(); + String packageName = componentName.getPackageName(); + + boolean mustPerformChecks = CompatChanges.isChangeEnabled( + REQUEST_LISTENING_MUST_MATCH_PACKAGE, callingUid); + + if (mustPerformChecks) { + // Check calling user can act on behalf of current user + userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid, + userId, false, ActivityManagerInternal.ALLOW_NON_FULL, + "requestTileServiceListeningState", packageName); + + // Check calling uid matches package + checkCallingUidPackage(packageName, callingUid, userId); + + int currentUser = mActivityManagerInternal.getCurrentUserId(); + + // Check current user + if (userId != currentUser) { + throw new IllegalArgumentException("User " + userId + " is not the current user."); + } + } + if (mBar != null) { + try { + mBar.requestTileServiceListeningState(componentName); + } catch (RemoteException e) { + Slog.e(TAG, "requestTileServiceListeningState", e); + } + } + } + + @Override public void requestAddTile( @NonNull ComponentName componentName, @NonNull CharSequence label, diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index bd4b8d15f453..cc1d0e2ea6c8 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -715,7 +715,7 @@ public class TrustManagerService extends SystemService { (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id); - if (enabledAgents == null) { + if (enabledAgents.isEmpty()) { if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id + ": no agents enabled by user"); continue; @@ -1080,9 +1080,7 @@ public class TrustManagerService extends SystemService { } List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId); - if (previouslyEnabledAgents != null) { - discoveredAgents.addAll(previouslyEnabledAgents); - } + discoveredAgents.addAll(previouslyEnabledAgents); utils.setEnabledTrustAgents(discoveredAgents, userId); Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId); diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java index 30e261725a73..092853f298c2 100644 --- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java @@ -39,7 +39,7 @@ import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; -import android.telephony.TelephonyManager.CarrierPrivilegesListener; +import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; @@ -98,8 +98,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener; @NonNull - private final List<CarrierPrivilegesListener> mCarrierPrivilegesChangedListeners = - new ArrayList<>(); + private final List<CarrierPrivilegesCallback> mCarrierPrivilegesCallbacks = new ArrayList<>(); @NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot; @@ -151,20 +150,21 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { executor, mSubscriptionChangedListener); mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener); - registerCarrierPrivilegesListeners(); + registerCarrierPrivilegesCallbacks(); } - private void registerCarrierPrivilegesListeners() { + // TODO(b/221306368): Refactor with the new onCarrierServiceChange in the new CPCallback + private void registerCarrierPrivilegesCallbacks() { final HandlerExecutor executor = new HandlerExecutor(mHandler); final int modemCount = mTelephonyManager.getActiveModemCount(); try { for (int i = 0; i < modemCount; i++) { - CarrierPrivilegesListener carrierPrivilegesListener = - new CarrierPrivilegesListener() { + CarrierPrivilegesCallback carrierPrivilegesCallback = + new CarrierPrivilegesCallback() { @Override public void onCarrierPrivilegesChanged( - @NonNull List<String> privilegedPackageNames, - @NonNull int[] privilegedUids) { + @NonNull Set<String> privilegedPackageNames, + @NonNull Set<Integer> privilegedUids) { // Re-trigger the synchronous check (which is also very cheap due // to caching in CarrierPrivilegesTracker). This allows consistency // with the onSubscriptionsChangedListener and broadcasts. @@ -172,9 +172,9 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } }; - mTelephonyManager.addCarrierPrivilegesListener( - i, executor, carrierPrivilegesListener); - mCarrierPrivilegesChangedListeners.add(carrierPrivilegesListener); + mTelephonyManager.registerCarrierPrivilegesCallback( + i, executor, carrierPrivilegesCallback); + mCarrierPrivilegesCallbacks.add(carrierPrivilegesCallback); } } catch (IllegalArgumentException e) { Slog.wtf(TAG, "Encounted exception registering carrier privileges listeners", e); @@ -191,15 +191,15 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener); mTelephonyManager.unregisterTelephonyCallback(mActiveDataSubIdListener); - unregisterCarrierPrivilegesListeners(); + unregisterCarrierPrivilegesCallbacks(); } - private void unregisterCarrierPrivilegesListeners() { - for (CarrierPrivilegesListener carrierPrivilegesListener : - mCarrierPrivilegesChangedListeners) { - mTelephonyManager.removeCarrierPrivilegesListener(carrierPrivilegesListener); + private void unregisterCarrierPrivilegesCallbacks() { + for (CarrierPrivilegesCallback carrierPrivilegesCallback : + mCarrierPrivilegesCallbacks) { + mTelephonyManager.unregisterCarrierPrivilegesCallback(carrierPrivilegesCallback); } - mCarrierPrivilegesChangedListeners.clear(); + mCarrierPrivilegesCallbacks.clear(); } /** @@ -283,7 +283,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } private void handleActionMultiSimConfigChanged(Context context, Intent intent) { - unregisterCarrierPrivilegesListeners(); + unregisterCarrierPrivilegesCallbacks(); // Clear invalid slotIds from the mReadySubIdsBySlotId map. final int modemCount = mTelephonyManager.getActiveModemCount(); @@ -296,7 +296,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } } - registerCarrierPrivilegesListeners(); + registerCarrierPrivilegesCallbacks(); handleSubscriptionsChanged(); } 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/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index a8dd856c2191..c0cdec9ade7f 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -657,7 +657,7 @@ class ActivityMetricsLogger { for (int i = mTransitionInfoList.size() - 2; i >= 0; i--) { final TransitionInfo prevInfo = mTransitionInfoList.get(i); if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.mVisibleRequested) { - abort(prevInfo, "nothing will be drawn"); + scheduleCheckActivityToBeDrawn(prevInfo.mLastLaunchedActivity, 0 /* delay */); } } } @@ -757,6 +757,10 @@ class ActivityMetricsLogger { /** Makes sure that the reference to the removed activity is cleared. */ void notifyActivityRemoved(@NonNull ActivityRecord r) { mLastTransitionInfo.remove(r); + final TransitionInfo info = getActiveTransitionInfo(r); + if (info != null) { + abort(info, "removed"); + } final int packageUid = r.info.applicationInfo.uid; final PackageCompatStateInfo compatStateInfo = mPackageUidToCompatStateInfo.get(packageUid); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2153f5f4dd70..883ce99d313d 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) { @@ -2476,7 +2476,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } private boolean transferSplashScreenIfNeeded() { - if (!mHandleExitSplashScreen || mStartingSurface == null || mStartingWindow == null + if (finishing || !mHandleExitSplashScreen || mStartingSurface == null + || mStartingWindow == null || mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_FINISH) { return false; } @@ -2914,7 +2915,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ boolean supportsPictureInPicture() { return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined() - && info.supportsPictureInPicture(); + && info.supportsPictureInPicture() + && (mDisplayContent != null && mDisplayContent.mDwpcHelper.isWindowingModeSupported( + WINDOWING_MODE_PINNED)); } /** @@ -9575,9 +9578,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/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 64f426187fd2..eb5ca9c2f43b 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -402,7 +402,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { activities.add(r.info); }); } - if (!displayContent.mDwpcHelper.canContainActivities(activities)) { + if (!displayContent.mDwpcHelper.canContainActivities(activities, + displayContent.getWindowingMode())) { return false; } } diff --git a/services/core/java/com/android/server/wm/BLASTSync.md b/services/core/java/com/android/server/wm/BLASTSync.md new file mode 100644 index 000000000000..2f39d6db385e --- /dev/null +++ b/services/core/java/com/android/server/wm/BLASTSync.md @@ -0,0 +1,108 @@ += What does it mean for BLAST Sync to work? = +There are two BLAST sync primitives on the server side, BLASTSyncEngine and applyWithNextDraw. +Both of them are used to solve subclasses of this category of problem: + 1. You have some server side changes, which will trigger both WM/SysUI initiated SurfaceControl.Transactions, + and also trigger a client redraw/update + 2. You want to synchronize the redraw of those clients with the application of those WM/SysUI side changes. + +Put simply, you would like to synchronize the graphical effects of some WM changes with the graphical output of various windows +observing those changes. + +To talk about exactly what the primitives guarantee, we need to clarify what we mean by server side changes. +In this document we will use a term syncable state to refer to any state mutated under the WindowManager lock +which when observed by the client, produces a visible outcome in the produced frame. +For example the current Configuration. + +The guarantee provided by Server-side BLAST Sync Primitives is thus: +Guarantee 1: If you make a set of changes to syncable state, at the same time that you begin a sync, +then the first frame drawn by the client after observing the syncable state will be sent in a transaction +to the consumer of the sync which was begun, rather than directly sent to SurfaceFlinger. + +Here "at the same time" means in the same critical section (while holding the WM lock) +For example this guarantee means that you can write code like: + window.performConfigurationChange(someConfiguration) + window.applyOnNextDraw(consumer) +And the consumer will always be passed the first frame containing the configuration change. This can work with any +syncable state not just Configuration. + +The following is the protocol and additional requirements for BLAST sync, and an analysis of why it is correct. Due to time +constraints we analyze it for a single window only (as this is actually the hard part). + +Protocol requirements: + Server protocol, precondition, begin a syncSeqId integer per window at 0: + SA: Enter the critical section + SB: Change syncable state, any number of times, prepare any number of syncs (and + increment the seqId if a sync was prepared, assosciate it with the sync) + SC: Leave the critical section + SD: Send syncable state updates to the client, always paired with the current seqId + SE: When the client calls finishDrawing, execute the consumer for each sync with + seqId <= the seqId which the client passed to finishDrawing + Client protocol: + CA: Observe state and seqid changes up until a fixed frame deadline, then execute performTraversals + CB: If the seqId is incremeneted at the time of the frame deadline, configure the renderer to + redirect the next draw in to a transaction, record the seqId at the time + CC: When the draw is finished, send the transaction containing the draw to WM with the + previously recorded seqId + Additional requirements/assumptions: + 1. The server may only send changes to the syncable state paired with the seqId. The client may + only receive them together (e.g. not from other sources) + 2. In between changing and sending syncable state, the lock must be released and acquired again + 3. The client wont draw a frame reflecting syncable state changes without passing through "performTraversals" + 4. Drawing never fails + 5. There are no blocking calls between the client or the server + +Note that the server can begin the protocol at any time, so it may be possible for the client to proceed through +phases SA, SB, SC, and SD multiple times before the client receives any messages. + +To show that the guarantee can't be violated, we use a notation of sequences, where we describe interleaving +of protocol events. For duplicate events, we attach a number, e.g. SA_1, SA_2. + +We proceed by contradiction, imagine there was some sequence (..., SA_N, ...) for which the guarantee was +not upheld. This means that either + 1. finishDrawing with the assosciate seqId was never sent to the server OR + 2. It was sent too late (after the first frame was sent to SF instead of WM) OR + 3. It was sent too early (not containing the state changes originating with SA_N) +If it was sent neither too late, nor too early, and contained the assosciated seqId, then protocol step SE +says that the frame will be passed to the consumer and we uphold our guarantee. + +The first case is impossible because step SD says that the server always sends the seqId if a sync was prepared. +If we send it the client must receive it. Since we only increment the seqId, and the client only takes the +seqId from us (requirement 1, protocol step SB), the received ID must be higher than the clients previous seqId. +CA says that performTraversals will execute, and CB says that when it does, if the seqId is higher than before +it will schedule the render to sync. Requirement 4 says drawing never fails, so CC must execute, and so we will always +eventually send every seqId (or a seqId > than it) back to the server. + +It also can't be sent too late. By requirement 2 we must release and acquire the lock +after after changing and before emitting syncable state changes. This means it's guaranteed +that even in an ordering like AcquireLock, ChangeState, PrepareSync, Release lock we can't +send the state changes before prepareSync, and so they can always include at least the seqId +assosciated with changestate (or a later one). +Since we only receive the SeqId with the State changes (requirement 1), +and we wont draw state changes without passing through perform traversals (requirement 3) the first frame +containing the state change must have been generated by a call to performTraversals which also observed +the seqId change, and so it will appropriately configure the renderer. + +By the same argument it can't be sent too early! Since we only send seqIds we receive from the server, +and we only send seqIds after completing a drawing pass of the assosciated state. + +So we can see that no matter at what time the server makes syncable state changes, the first frame will +always be delivered to the draw handler. Assuming that the client and server uphold this protocol and these +requirements. + +The trickiest part of the implementation at the moment is due to assosciating seqId. Currently we send one of the most +most important pieces of syncable state (configuration) over multiple channels. Namely ClientTransaction +and MSG_RESIZED. The ordering of these relative to sync preparation in server code is undefined, in fact we have cases like +this all the time: + acquireLock() + changeConfiguration() + // time passes, but still in critical section + prepareSync() + releaseLock() +This is exactly the kind of case Guarantee 1 mentions as an example. In previous incarnations of the code this worked +because relayoutWindow needed to acquire the same lock and relayoutWindow was a necessary part of completing sync. + +Now that we have no barrier, that could create issues, because at the time we change configuration (and send the change +to the client via ClientTransaction), we haven't even incremented the seqId yet, and so how can the client observe it +at the same time as the state? We solve this by pushing all client communication through a handler thread that has to +acquire the lock. This ensures we uphold requirement 2. + diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 23f14a7b7a16..dbc01413e6fa 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -25,6 +25,7 @@ import android.content.ComponentName; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; +import android.os.Bundle; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SystemProperties; @@ -44,7 +45,11 @@ import com.android.internal.protolog.common.ProtoLog; class BackNavigationController { private static final String TAG = "BackNavigationController"; - private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; + // By default, enable new back dispatching without any animations. + private static final int BACK_PREDICTABILITY_PROP = + SystemProperties.getInt("persist.debug.back_predictability", 1); + private static final int ANIMATIONS_MASK = 1 << 1; + private static final int SCREENSHOT_MASK = 1 << 2; @Nullable private TaskSnapshotController mTaskSnapshotController; @@ -53,11 +58,15 @@ class BackNavigationController { * Returns true if the back predictability feature is enabled */ static boolean isEnabled() { - return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 0) > 0; + return BACK_PREDICTABILITY_PROP > 0; } static boolean isScreenshotEnabled() { - return false; + return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0; + } + + private static boolean isAnimationEnabled() { + return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0; } /** @@ -93,14 +102,17 @@ class BackNavigationController { ActivityRecord prev; WindowContainer<?> removedWindowContainer; ActivityRecord activityRecord; + ActivityRecord prevTaskTopActivity = null; SurfaceControl animationLeashParent; WindowConfiguration taskWindowConfiguration; HardwareBuffer screenshotBuffer = null; + SurfaceControl screenshotSurface; int prevTaskId; int prevUserId; RemoteAnimationTarget topAppTarget; SurfaceControl animLeash; - IOnBackInvokedCallback callback = null; + IOnBackInvokedCallback applicationCallback = null; + IOnBackInvokedCallback systemCallback = null; synchronized (task.mWmService.mGlobalLock) { @@ -116,15 +128,14 @@ class BackNavigationController { removedWindowContainer = activityRecord; taskWindowConfiguration = window.getWindowConfiguration(); } - IOnBackInvokedCallback applicationCallback = null; - IOnBackInvokedCallback systemCallback = null; if (window != null) { applicationCallback = window.getApplicationOnBackInvokedCallback(); - callback = applicationCallback; - if (callback == null) { - systemCallback = window.getSystemOnBackInvokedCallback(); - callback = systemCallback; - } + systemCallback = window.getSystemOnBackInvokedCallback(); + } + if (applicationCallback == null && systemCallback == null) { + // Return null when either there's no window, or apps have just initialized and + // have not finished registering callbacks. + return null; } ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, " @@ -133,24 +144,24 @@ class BackNavigationController { task, activityRecord, applicationCallback, systemCallback); // TODO Temp workaround for Sysui until b/221071505 is fixed - if (activityRecord == null && callback != null) { + if (activityRecord == null && applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, - callback /* onBackInvokedCallback */); + applicationCallback /* onBackInvokedCallback */); } // For IME and Home, either a callback is registered, or we do nothing. In both cases, // we don't need to pass the leashes below. if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible() || activityRecord.isActivityTypeHome()) { - if (callback != null) { + if (applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, - callback /* onBackInvokedCallback */); + applicationCallback /* onBackInvokedCallback */); } else { return null; } @@ -159,12 +170,12 @@ class BackNavigationController { prev = task.getActivity( (r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity()); - if (callback != null) { + if (applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, - callback /* onBackInvokedCallback */); + applicationCallback /* onBackInvokedCallback */); } else if (prev != null) { backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY; } else if (task.returnsToHomeRootTask()) { @@ -188,8 +199,8 @@ class BackNavigationController { prevTaskId = prevTask != null ? prevTask.mTaskId : 0; prevUserId = prevTask != null ? prevTask.mUserId : 0; - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s", - prev != null ? prev.mActivityComponent : null); + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. " + + "Back type is %s", prev != null ? prev.mActivityComponent : null, backType); //TODO(207481538) Remove once the infrastructure to support per-activity screenshot is // implemented. For now we simply have the mBackScreenshots hash map that dumbly @@ -204,6 +215,7 @@ class BackNavigationController { return null; } // Prepare a leash to animate the current top window + // TODO(b/220934562): Use surface animator to better manage animation conflicts. animLeash = removedWindowContainer.makeAnimationLeash() .setName("BackPreview Leash for " + removedWindowContainer) .setHidden(false) @@ -231,12 +243,30 @@ class BackNavigationController { activityRecord.windowType); } - SurfaceControl.Builder builder = new SurfaceControl.Builder() + screenshotSurface = new SurfaceControl.Builder() .setName("BackPreview Screenshot for " + prev) .setParent(animationLeashParent) .setHidden(false) - .setBLASTLayer(); - SurfaceControl screenshotSurface = builder.build(); + .setBLASTLayer() + .build(); + if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { + task.mBackGestureStarted = true; + // Make launcher show from behind by marking its top activity as visible and + // launch-behind to bump its visibility for the duration of the back gesture. + prevTaskTopActivity = prevTask.getTopNonFinishingActivity(); + if (prevTaskTopActivity != null) { + if (!prevTaskTopActivity.mVisibleRequested) { + prevTaskTopActivity.setVisibility(true); + } + prevTaskTopActivity.mLaunchTaskBehind = true; + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, + "Setting Activity.mLauncherTaskBehind to true. Activity=%s", + prevTaskTopActivity); + prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible( + null /* starting */, 0 /* configChanges */, + false /* preserveWindows */); + } + } // Find a screenshot of the previous activity @@ -253,17 +283,20 @@ class BackNavigationController { WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; try { - activityRecord.token.linkToDeath( - () -> resetSurfaces(finalRemovedWindowContainer), 0); + activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death", e); resetSurfaces(removedWindowContainer); return null; } - RemoteCallback onBackNavigationDone = new RemoteCallback( - result -> resetSurfaces(finalRemovedWindowContainer - )); + int finalBackType = backType; + final IOnBackInvokedCallback callback = + applicationCallback != null ? applicationCallback : systemCallback; + ActivityRecord finalPrevTaskTopActivity = prevTaskTopActivity; + RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone( + result, finalRemovedWindowContainer, finalBackType, task, + finalPrevTaskTopActivity)); return new BackNavigationInfo(backType, topAppTarget, screenshotSurface, @@ -273,6 +306,39 @@ class BackNavigationController { callback); } + private void onBackNavigationDone( + Bundle result, WindowContainer windowContainer, int backType, + Task task, ActivityRecord prevTaskTopActivity) { + SurfaceControl surfaceControl = windowContainer.getSurfaceControl(); + boolean triggerBack = result != null + ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK) + : false; + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, " + + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity); + + if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { + if (triggerBack) { + if (surfaceControl != null && surfaceControl.isValid()) { + // When going back to home, hide the task surface before it is re-parented to + // avoid flicker. + SurfaceControl.Transaction t = windowContainer.getSyncTransaction(); + t.hide(surfaceControl); + t.apply(); + } + } + if (prevTaskTopActivity != null && !triggerBack) { + // Restore the launch-behind state. + task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token); + prevTaskTopActivity.mLaunchTaskBehind = false; + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, + "Setting Activity.mLauncherTaskBehind to false. Activity=%s", + prevTaskTopActivity); + } + } else { + task.mBackGestureStarted = false; + } + resetSurfaces(windowContainer); + } private HardwareBuffer getActivitySnapshot(@NonNull Task task, ComponentName activityComponent) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index d1b9a7895058..736732029510 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -145,7 +145,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; -import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; @@ -4270,17 +4269,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { + if (mImeLayeringTarget != null && mImeInputTarget != null + && mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord()) { + // Do not change parent if the window hasn't requested IME. + return null; + } // Attach it to app if the target is part of an app and such app is covering the entire // screen. If it's not covering the entire screen the IME might extend beyond the apps // bounds. if (shouldImeAttachedToApp()) { - if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord()) { - // Do not change parent if the window hasn't requested IME. - return null; - } return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); } - // Otherwise, we just attach it to where the display area policy put it. return mImeWindowsContainer.getParent() != null ? mImeWindowsContainer.getParent().getSurfaceControl() : null; @@ -4504,56 +4503,38 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mTmpUpdateAllDrawn.clear(); - int repeats = 0; - do { - repeats++; - if (repeats > 6) { - Slog.w(TAG, "Animation repeat aborted after too many iterations"); - clearLayoutNeeded(); - break; - } - - if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", - pendingLayoutChanges); - - if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { - mWallpaperController.adjustWallpaperWindows(); - } + if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", + pendingLayoutChanges); - if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); - if (updateOrientation()) { - setLayoutNeeded(); - sendNewConfiguration(); - } - } + if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { + mWallpaperController.adjustWallpaperWindows(); + } - if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { + if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { + if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); + if (updateOrientation()) { setLayoutNeeded(); + sendNewConfiguration(); } + } - // FIRST LOOP: Perform a layout, if needed. - if (repeats < LAYOUT_REPEAT_THRESHOLD) { - performLayout(repeats == 1, false /* updateInputWindows */); - } else { - Slog.w(TAG, "Layout repeat skipped after too many iterations"); - } + if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { + setLayoutNeeded(); + } - // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating. - pendingLayoutChanges = 0; + // Perform a layout, if needed. + performLayout(true /* initial */, false /* updateInputWindows */); + pendingLayoutChanges = 0; - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy"); - try { - mDisplayPolicy.beginPostLayoutPolicyLw(); - forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */); - pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw(); - } finally { - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - } - if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( - "after finishPostLayoutPolicyLw", pendingLayoutChanges); - mInsetsStateController.onPostLayout(); - } while (pendingLayoutChanges != 0); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy"); + try { + mDisplayPolicy.beginPostLayoutPolicyLw(); + forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */); + mDisplayPolicy.finishPostLayoutPolicyLw(); + } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + } + mInsetsStateController.onPostLayout(); mTmpApplySurfaceChangesTransactionState.reset(); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 4148d8b7d853..bb5dacc89bc2 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -42,11 +42,9 @@ import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; @@ -79,7 +77,6 @@ import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT; -import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE; @@ -136,6 +133,7 @@ import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants; import android.view.accessibility.AccessibilityManager; +import android.window.ClientWindowFrames; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -340,15 +338,12 @@ public class DisplayPolicy { private static final Rect sTmpRect2 = new Rect(); private static final Rect sTmpLastParentFrame = new Rect(); private static final Rect sTmpDisplayCutoutSafe = new Rect(); - private static final Rect sTmpDisplayFrame = new Rect(); - private static final Rect sTmpParentFrame = new Rect(); - private static final Rect sTmpFrame = new Rect(); + private static final ClientWindowFrames sTmpClientFrames = new ClientWindowFrames(); private final WindowLayout mWindowLayout = new WindowLayout(); private WindowState mTopFullscreenOpaqueWindowState; private boolean mTopIsFullscreen; - private boolean mForceStatusBar; private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; private boolean mForceShowSystemBars; @@ -940,6 +935,26 @@ public class DisplayPolicy { break; } + if (LayoutParams.isSystemAlertWindowType(attrs.type)) { + float maxOpacity = mService.mMaximumObscuringOpacityForTouch; + if (attrs.alpha > maxOpacity + && (attrs.flags & FLAG_NOT_TOUCHABLE) != 0 + && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) { + // The app is posting a SAW with the intent of letting touches pass through, but + // they are going to be deemed untrusted and will be blocked. Try to honor the + // intent of letting touches pass through at the cost of 0.2 opacity for app + // compatibility reasons. More details on b/218777508. + Slog.w(TAG, String.format( + "App %s has a system alert window (type = %d) with FLAG_NOT_TOUCHABLE and " + + "LayoutParams.alpha = %.2f > %.2f, setting alpha to %.2f to " + + "let touches pass through (if this is isn't desirable, remove " + + "flag FLAG_NOT_TOUCHABLE).", + attrs.packageName, attrs.type, attrs.alpha, maxOpacity, maxOpacity)); + attrs.alpha = maxOpacity; + win.mWinAnimator.mAlpha = maxOpacity; + } + } + // Check if alternate bars positions were updated. if (mStatusBarAlt == win) { mStatusBarAltPosition = getAltBarPosition(attrs); @@ -1474,8 +1489,8 @@ public class DisplayPolicy { displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), null /* attachedWindowFrame */, win.mGlobalScale, - sTmpDisplayFrame, sTmpParentFrame, sTmpFrame); - controller.computeSimulatedState(win, displayFrames, sTmpFrame); + sTmpClientFrames); + controller.computeSimulatedState(win, displayFrames, sTmpClientFrames.frame); } } @@ -1518,12 +1533,12 @@ public class DisplayPolicy { sTmpLastParentFrame.set(pf); - final boolean clippedByDisplayCutout = mWindowLayout.computeFrames(attrs, - win.getInsetsState(), displayFrames.mDisplayCutoutSafe, + mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe, win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight, win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale, - df, pf, f); - windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout); + sTmpClientFrames); + windowFrames.setParentFrameWasClippedByDisplayCutout( + sTmpClientFrames.isParentFrameClippedByDisplayCutout); if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() + ": sim=#" + Integer.toHexString(attrs.softInputMode) @@ -1536,7 +1551,7 @@ public class DisplayPolicy { windowFrames.setContentChanged(true); } - win.setFrame(); + win.setFrames(sTmpClientFrames); } WindowState getTopFullscreenOpaqueWindow() { @@ -1558,7 +1573,6 @@ public class DisplayPolicy { mStatusBarBackgroundWindows.clear(); mStatusBarColorCheckedBounds.setEmpty(); mStatusBarBackgroundCheckedBounds.setEmpty(); - mForceStatusBar = false; mAllowLockscreenWhenOn = false; mShowingDream = false; @@ -1599,9 +1613,6 @@ public class DisplayPolicy { && attrs.type < FIRST_SYSTEM_WINDOW; if (mTopFullscreenOpaqueWindowState == null) { final int fl = attrs.flags; - if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { - mForceStatusBar = true; - } if (win.isDreamWindow()) { // If the lockscreen was showing when the dream started then wait // for the dream to draw before hiding the lockscreen. @@ -1710,21 +1721,9 @@ public class DisplayPolicy { } /** - * Called following layout of all windows and after policy has been applied - * to each window. If in this function you do - * something that may have modified the animation state of another window, - * be sure to return non-zero in order to perform another pass through layout. - * - * @return Return any bit set of - * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT}, - * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG}, - * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or - * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}. + * Called following layout of all windows and after policy has been applied to each window. */ - public int finishPostLayoutPolicyLw() { - int changes = 0; - boolean topIsFullscreen = false; - + public void finishPostLayoutPolicyLw() { // If we are not currently showing a dream then remember the current // lockscreen state. We will use this to determine whether the dream // started while the lockscreen was showing and remember this state @@ -1733,41 +1732,6 @@ public class DisplayPolicy { mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded(); } - if (getStatusBar() != null) { - if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar - + " top=" + mTopFullscreenOpaqueWindowState); - final boolean forceShowStatusBar = (getStatusBar().getAttrs().privateFlags - & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; - - boolean topAppHidesStatusBar = topAppHidesStatusBar(); - if (mForceStatusBar || forceShowStatusBar) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); - // Maintain fullscreen layout until incoming animation is complete. - topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); - } else if (mTopFullscreenOpaqueWindowState != null) { - topIsFullscreen = topAppHidesStatusBar; - // The subtle difference between the window for mTopFullscreenOpaqueWindowState - // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window - // requests to hide the status bar. Not sure if there is another way that to be the - // case though. - if (!topIsFullscreen) { - topAppHidesStatusBar = false; - } - } - StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); - if (statusBar != null) { - statusBar.setTopAppHidesStatusBar(topAppHidesStatusBar); - } - } - - if (mTopIsFullscreen != topIsFullscreen) { - if (!topIsFullscreen) { - // Force another layout when status bar becomes fully shown. - changes |= FINISH_LAYOUT_REDO_LAYOUT; - } - mTopIsFullscreen = topIsFullscreen; - } - updateSystemBarAttributes(); if (mShowingDream != mLastShowingDream) { @@ -1777,7 +1741,6 @@ public class DisplayPolicy { } mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn); - return changes; } /** @@ -2441,6 +2404,18 @@ public class DisplayPolicy { mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible; mDisplayContent.getInsetsPolicy().updateBarControlTarget(win); + final boolean topAppHidesStatusBar = topAppHidesStatusBar(); + if (getStatusBar() != null) { + final StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); + if (statusBar != null) { + statusBar.setTopAppHidesStatusBar(topAppHidesStatusBar); + } + } + + // If the top app is not fullscreen, only the default rotation animation is allowed. + mTopIsFullscreen = topAppHidesStatusBar + && (mNotificationShade == null || !mNotificationShade.isVisible()); + int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS; appearance = configureStatusBarOpacity(appearance); appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible, @@ -2781,7 +2756,6 @@ public class DisplayPolicy { } } pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen); - pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); pw.print(prefix); pw.print("mForceShowNavigationBarEnabled="); pw.print(mForceShowNavigationBarEnabled); pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java index 60d2a5da9286..27d46ecfb91a 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java +++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java @@ -18,6 +18,7 @@ package com.android.server.wm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.os.UserHandle; import android.util.ArraySet; @@ -63,13 +64,14 @@ class DisplayWindowPolicyControllerHelper { } /** - * @see DisplayWindowPolicyController#canContainActivities(List) + * @see DisplayWindowPolicyController#canContainActivities(List, int) */ - public boolean canContainActivities(@NonNull List<ActivityInfo> activities) { + public boolean canContainActivities(@NonNull List<ActivityInfo> activities, + @WindowConfiguration.WindowingMode int windowingMode) { if (mDisplayWindowPolicyController == null) { return true; } - return mDisplayWindowPolicyController.canContainActivities(activities); + return mDisplayWindowPolicyController.canContainActivities(activities, windowingMode); } /** @@ -126,6 +128,17 @@ class DisplayWindowPolicyControllerHelper { } } + /** + * @see DisplayWindowPolicyController#isWindowingModeSupported(int) + */ + public final boolean isWindowingModeSupported( + @WindowConfiguration.WindowingMode int windowingMode) { + if (mDisplayWindowPolicyController == null) { + return true; + } + return mDisplayWindowPolicyController.isWindowingModeSupported(windowingMode); + } + void dump(String prefix, PrintWriter pw) { if (mDisplayWindowPolicyController != null) { pw.println(); diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 398816b331cb..3951c567e89c 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -424,14 +424,12 @@ class InsetsPolicy { return state; } } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { - // During switching tasks with gestural navigation, if the IME is attached to - // one app window on that time, even the next app window is behind the IME window, - // conceptually the window should not receive the IME insets if the next window is - // not eligible IME requester and ready to show IME on top of it. - final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp(); + // During switching tasks with gestural navigation, before the next IME input target + // starts the input, we should adjust and freeze the last IME visibility of the window + // in case delivering obsoleted IME insets state during transitioning. final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME); - if (shouldImeAttachedToApp && originalImeSource != null) { + if (originalImeSource != null) { final boolean imeVisibility = w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME); final InsetsState state = copyState ? new InsetsState(originalState) diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java index 4e7f1d4cca18..b9aa9599babe 100644 --- a/services/core/java/com/android/server/wm/MirrorActiveUids.java +++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java @@ -19,7 +19,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import android.app.ActivityManager.ProcessState; -import android.util.SparseArray; +import android.util.SparseIntArray; import java.io.PrintWriter; @@ -29,15 +29,14 @@ import java.io.PrintWriter; * adjustment) or getting state from window manager (background start check). */ class MirrorActiveUids { - private final SparseArray<UidRecord> mUidStates = new SparseArray<>(); + /** Uid -> process state. */ + private final SparseIntArray mUidStates = new SparseIntArray(); + + /** Uid -> number of non-app visible windows belong to the uid. */ + private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray(); synchronized void onUidActive(int uid, int procState) { - UidRecord r = mUidStates.get(uid); - if (r == null) { - r = new UidRecord(); - mUidStates.put(uid, r); - } - r.mProcState = procState; + mUidStates.put(uid, procState); } synchronized void onUidInactive(int uid) { @@ -45,22 +44,28 @@ class MirrorActiveUids { } synchronized void onUidProcStateChanged(int uid, int procState) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mProcState = procState; + final int index = mUidStates.indexOfKey(uid); + if (index >= 0) { + mUidStates.setValueAt(index, procState); } } synchronized @ProcessState int getUidState(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null ? r.mProcState : PROCESS_STATE_NONEXISTENT; + return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT); } /** Called when the surface of non-application (exclude toast) window is shown or hidden. */ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mNumNonAppVisibleWindow += visible ? 1 : -1; + final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid); + if (index >= 0) { + final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); + if (num > 0) { + mNumNonAppVisibleWindowMap.setValueAt(index, num); + } else { + mNumNonAppVisibleWindowMap.removeAt(index); + } + } else if (visible) { + mNumNonAppVisibleWindowMap.append(uid, 1); } } @@ -70,23 +75,15 @@ class MirrorActiveUids { * {@link VisibleActivityProcessTracker}. */ synchronized boolean hasNonAppVisibleWindow(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null && r.mNumNonAppVisibleWindow > 0; + return mNumNonAppVisibleWindowMap.get(uid) > 0; } synchronized void dump(PrintWriter pw, String prefix) { - pw.print(prefix + "NumNonAppVisibleWindowByUid:["); - for (int i = mUidStates.size() - 1; i >= 0; i--) { - final UidRecord r = mUidStates.valueAt(i); - if (r.mNumNonAppVisibleWindow > 0) { - pw.print(" " + mUidStates.keyAt(i) + ":" + r.mNumNonAppVisibleWindow); - } + pw.print(prefix + "NumNonAppVisibleWindowUidMap:["); + for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) { + pw.print(" " + mNumNonAppVisibleWindowMap.keyAt(i) + ":" + + mNumNonAppVisibleWindowMap.valueAt(i)); } pw.println("]"); } - - private static final class UidRecord { - @ProcessState int mProcState; - int mNumNonAppVisibleWindow; - } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index a407021c7594..a4d338c06708 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -553,10 +553,6 @@ public class RecentsAnimationController implements DeathRecipient { mPendingStart = false; - // Perform layout if it was scheduled before to make sure that we get correct content - // insets for the target app window after a rotation - mDisplayContent.performLayout(false /* initial */, false /* updateInputWindows */); - final Rect contentInsets; final WindowState targetAppMainWindow = getTargetAppMainWindow(); if (targetAppMainWindow != null) { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 235533341433..94fc51dc94d2 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -3376,11 +3376,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return new ArrayList<>(); } } else { + final RecentTasks recentTasks = mWindowManager.mAtmService.getRecentTasks(); + final int recentsComponentUid = recentTasks != null + ? recentTasks.getRecentsComponentUid() + : -1; final ArrayList<ActivityRecord> activities = new ArrayList<>(); - forAllRootTasks(rootTask -> { - if (!dumpVisibleRootTasksOnly || rootTask.shouldBeVisible(null)) { - activities.addAll(rootTask.getDumpActivitiesLocked(name, userId)); + forAllLeafTasks(task -> { + final boolean isRecents = (task.effectiveUid == recentsComponentUid); + if (!dumpVisibleRootTasksOnly || task.shouldBeVisible(null) || isRecents) { + activities.addAll(task.getDumpActivitiesLocked(name, userId)); } + return false; }); return activities; } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 0c60919180fa..9ad25ac8876f 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -232,14 +232,14 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { int requestedWidth, int requestedHeight, int viewFlags, int flags, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) { if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); int res = mService.relayoutWindow(this, window, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrames, mergedConfiguration, outSurfaceControl, outInsetsState, - outActiveControls); + outActiveControls, outSyncSeqIdBundle); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); @@ -265,9 +265,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { @Override public void finishDrawing(IWindow window, - @Nullable SurfaceControl.Transaction postDrawTransaction) { + @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) { if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window); - mService.finishDrawingWindow(this, window, postDrawTransaction); + mService.finishDrawingWindow(this, window, postDrawTransaction, seqId); } @Override diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 8edb3137c416..f71bd7288532 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -72,6 +72,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; @@ -609,6 +610,12 @@ class Task extends TaskFragment { boolean mLastSurfaceShowing = true; + /** + * Tracks if a back gesture is in progress. + * Skips any system transition animations if this is set to {@code true}. + */ + boolean mBackGestureStarted = false; + private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, String _rootAffinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, @@ -1623,12 +1630,16 @@ class Task extends TaskFragment { } ActivityRecord performClearTop(ActivityRecord newR, int launchFlags) { + // The task should be preserved for putting new activity in case the last activity is + // finished if it is normal launch mode and not single top ("clear-task-top"). + mReuseTask = true; mTaskSupervisor.beginDeferResume(); final ActivityRecord result; try { result = clearTopActivities(newR, launchFlags); } finally { mTaskSupervisor.endDeferResume(); + mReuseTask = false; } return result; } @@ -3322,6 +3333,14 @@ class Task extends TaskFragment { } }); } + } else if (mBackGestureStarted) { + // Cancel playing transitions if a back navigation animation is in progress. + // This bit is set by {@link BackNavigationController} when a back gesture is started. + // It is used as a one-off transition overwrite that is cleared when the back gesture + // is committed and triggers a transition, or when the gesture is cancelled. + mBackGestureStarted = false; + mDisplayContent.mSkipAppTransitionAnimation = true; + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this); } else { super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources); } @@ -3403,7 +3422,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 +3475,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 +4373,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..21ca4bb6038b 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -216,6 +216,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } Task getTransientLaunchRestoreTarget(@NonNull WindowContainer container) { + if (mTransientLaunches == null) return null; for (int i = 0; i < mTransientLaunches.size(); ++i) { if (mTransientLaunches.keyAt(i).isDescendantOf(container)) { return mTransientLaunches.valueAt(i); @@ -491,7 +492,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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6718235e8982..d5f7a22a3d2b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -745,6 +745,9 @@ public class WindowManagerService extends IWindowManager.Stub private final DisplayHashController mDisplayHashController; + volatile float mMaximumObscuringOpacityForTouch = + InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH; + @VisibleForTesting final WindowContextListenerController mWindowContextListenerController = new WindowContextListenerController(); @@ -782,6 +785,8 @@ public class WindowManagerService extends IWindowManager.Stub DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR); private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor( DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH); + private final Uri mMaximumObscuringOpacityForTouchUri = Settings.Global.getUriFor( + Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); public SettingsObserver() { super(new Handler()); @@ -806,6 +811,8 @@ public class WindowManagerService extends IWindowManager.Stub UserHandle.USER_ALL); resolver.registerContentObserver(mDisplaySettingsPathUri, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this, + UserHandle.USER_ALL); } @Override @@ -849,6 +856,11 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (mMaximumObscuringOpacityForTouchUri.equals(uri)) { + updateMaximumObscuringOpacityForTouch(); + return; + } + @UpdateAnimationScaleMode final int mode; if (mWindowAnimationScaleUri.equals(uri)) { @@ -868,6 +880,14 @@ public class WindowManagerService extends IWindowManager.Stub void loadSettings() { updateSystemUiSettings(false /* handleChange */); updatePointerLocation(); + updateMaximumObscuringOpacityForTouch(); + } + + void updateMaximumObscuringOpacityForTouch() { + ContentResolver resolver = mContext.getContentResolver(); + mMaximumObscuringOpacityForTouch = Settings.Global.getFloat(resolver, + Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, + InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); } void updateSystemUiSettings(boolean handleChange) { @@ -2192,7 +2212,7 @@ public class WindowManagerService extends IWindowManager.Stub int requestedWidth, int requestedHeight, int viewVisibility, int flags, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) { Arrays.fill(outActiveControls, null); int result = 0; boolean configChanged; @@ -2617,7 +2637,7 @@ public class WindowManagerService extends IWindowManager.Stub } void finishDrawingWindow(Session session, IWindow client, - @Nullable SurfaceControl.Transaction postDrawTransaction) { + @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) { if (postDrawTransaction != null) { postDrawTransaction.sanitize(); } @@ -2628,7 +2648,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowState win = windowForClientLocked(session, client, false); ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s", win, (win != null ? win.mWinAnimator.drawStateToString() : "null")); - if (win != null && win.finishDrawing(postDrawTransaction)) { + if (win != null && win.finishDrawing(postDrawTransaction, seqId)) { if (win.hasWallpaper()) { win.getDisplayContent().pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 1cf4c1b0fbb2..5a2f28f4a365 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -566,9 +566,14 @@ public class WindowManagerShellCommand extends ShellCommand { try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) { ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>(); synchronized (mInternal.mGlobalLock) { + final RecentTasks recentTasks = mInternal.mAtmService.getRecentTasks(); + final int recentsComponentUid = recentTasks != null + ? recentTasks.getRecentsComponentUid() + : -1; // Request dump from all windows parallelly before writing to disk. mInternal.mRoot.forAllWindows(w -> { - if (w.isVisible()) { + final boolean isRecents = (w.getUid() == recentsComponentUid); + if (w.isVisible() || isRecents) { ByteTransferPipe pipe = null; try { pipe = new ByteTransferPipe(); 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/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index db687f627bfa..f66739293512 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1393,13 +1393,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } // TODO(b/161810301): Make the frame be passed from the client side. - void setFrame() { - // TODO(b/161810301): Set the window frame here. We don't have to do it now because - // DisplayPolicy has already done it for the window. - + void setFrames(ClientWindowFrames clientWindowFrames) { mHaveFrame = true; final WindowFrames windowFrames = mWindowFrames; + windowFrames.mDisplayFrame.set(clientWindowFrames.displayFrame); + windowFrames.mParentFrame.set(clientWindowFrames.parentFrame); + windowFrames.mFrame.set(clientWindowFrames.frame); if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { mLastRequestedWidth = mRequestedWidth; @@ -3946,7 +3946,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP try { mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration, - forceRelayout, alwaysConsumeSystemBars, displayId); + forceRelayout, alwaysConsumeSystemBars, displayId, Integer.MAX_VALUE); if (drawPending && reportOrientation && mOrientationChanging) { mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime(); ProtoLog.v(WM_DEBUG_ORIENTATION, @@ -5938,7 +5938,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP super.finishSync(outMergedTransaction, cancel); } - boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) { + boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) { if (mOrientationChangeRedrawRequestTime > 0) { final long duration = SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime; @@ -5985,7 +5985,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void immediatelyNotifyBlastSync() { prepareDrawHandlers(); - finishDrawing(null); + finishDrawing(null, Integer.MAX_VALUE); mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); if (!useBLASTSync()) return; } diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 1c6a3b5eb03f..0cd949457cd1 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -106,7 +106,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_HardwarePropertiesManagerService(env); register_android_server_storage_AppFuse(env); register_android_server_SyntheticPasswordManager(env); - register_android_graphics_GraphicsStatsService(env); register_android_hardware_display_DisplayViewport(env); register_android_server_am_CachedAppOptimizer(env); register_android_server_am_LowMemDetector(env); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index fa2850a5157d..f7c66c5cff69 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -293,8 +293,6 @@ public final class SystemServer implements Dumpable { "com.android.server.wifi.p2p.WifiP2pService"; private static final String LOWPAN_SERVICE_CLASS = "com.android.server.lowpan.LowpanService"; - private static final String ETHERNET_SERVICE_CLASS = - "com.android.server.ethernet.EthernetService"; private static final String JOB_SCHEDULER_SERVICE_CLASS = "com.android.server.job.JobSchedulerService"; private static final String LOCK_SETTINGS_SERVICE_CLASS = @@ -423,6 +421,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"; @@ -1993,13 +1993,6 @@ public final class SystemServer implements Dumpable { t.traceEnd(); } - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) || - mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { - t.traceBegin("StartEthernet"); - mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS); - t.traceEnd(); - } - t.traceBegin("StartPacProxyService"); try { pacProxyService = new PacProxyService(context); @@ -2608,6 +2601,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/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java index f05658bf6b0b..e09668756f10 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -494,9 +494,9 @@ public class AlarmManagerServiceTest { final ArgumentCaptor<AlarmManagerService.UninstallReceiver> packageReceiverCaptor = ArgumentCaptor.forClass(AlarmManagerService.UninstallReceiver.class); - verify(mMockContext).registerReceiver(packageReceiverCaptor.capture(), + verify(mMockContext).registerReceiverForAllUsers(packageReceiverCaptor.capture(), argThat((filter) -> filter.hasAction(Intent.ACTION_PACKAGE_ADDED) - && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED))); + && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)), isNull(), isNull()); mPackageChangesReceiver = packageReceiverCaptor.getValue(); assertEquals(mService.mExactAlarmCandidates, Collections.emptySet()); 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/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS index 46b797b83f1d..5181af14ff65 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS +++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS @@ -1,3 +1,4 @@ include /services/core/java/com/android/server/pm/OWNERS +per-file BackgroundDexOptServiceUnitTest.java = file:/services/core/java/com/android/server/pm/dex/OWNERS per-file StagingManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com 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..97b52a98b266 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt @@ -24,7 +24,6 @@ import android.os.Build import android.os.storage.StorageManager import android.util.ArrayMap import android.util.PackageUtils -import com.android.internal.util.FunctionalUtils import com.android.server.SystemConfig.SharedLibraryEntry import com.android.server.compat.PlatformCompat import com.android.server.extendedtestutils.wheneverStatic @@ -35,7 +34,6 @@ import com.android.server.pm.parsing.pkg.ParsedPackage import com.android.server.testutils.any import com.android.server.testutils.eq import com.android.server.testutils.mock -import com.android.server.testutils.mockThrowOnUnmocked import com.android.server.testutils.nullable import com.android.server.testutils.spy import com.android.server.testutils.whenever @@ -59,6 +57,7 @@ import kotlin.test.assertFailsWith import kotlin.test.assertFalse import kotlin.test.assertTrue +@Ignore("b/216603387") @RunWith(JUnit4::class) class SharedLibrariesImplTest { @@ -85,6 +84,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 +114,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 +183,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)!! @@ -253,7 +248,6 @@ class SharedLibrariesImplTest { assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) } - @Ignore("b/216603387") @Test fun updateSharedLibraries_withStaticLibPackage() { val testPackageSetting = mExistingSettings[STATIC_LIB_PACKAGE_NAME]!! @@ -266,7 +260,6 @@ class SharedLibrariesImplTest { assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(DYNAMIC_LIB_PACKAGE_NAME)) } - @Ignore("b/216603387") @Test fun updateSharedLibraries_withConsumerPackage() { val testPackageSetting = mExistingSettings[CONSUMER_PACKAGE_NAME]!! @@ -280,7 +273,6 @@ class SharedLibrariesImplTest { assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(STATIC_LIB_PACKAGE_NAME)) } - @Ignore("b/216603387") @Test fun updateAllSharedLibraries() { mExistingSettings.forEach { 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/mockingservicestests/src/com/android/server/tare/AgentTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java index 41d46f223f4b..534d0a1bc76f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java @@ -21,7 +21,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import android.app.AlarmManager; import android.content.Context; @@ -71,10 +70,10 @@ public class AgentTest { .strictness(Strictness.LENIENT) .mockStatic(LocalServices.class) .startMocking(); - when(mIrs.getContext()).thenReturn(mContext); - when(mIrs.getCompleteEconomicPolicyLocked()).thenReturn(mEconomicPolicy); - when(mIrs.getLock()).thenReturn(mIrs); - when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class)); + doReturn(mContext).when(mIrs).getContext(); + doReturn(mEconomicPolicy).when(mIrs).getCompleteEconomicPolicyLocked(); + doReturn(mIrs).when(mIrs).getLock(); + doReturn(mock(AlarmManager.class)).when(mContext).getSystemService(Context.ALARM_SERVICE); mScribe = new MockScribe(mIrs); } diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java index ab29e5903f02..c2cf2ff439ca 100644 --- a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java @@ -109,6 +109,7 @@ public class ScribeTest { long lastReclamationTime = System.currentTimeMillis(); long remainingConsumableNarcs = 2000L; long consumptionLimit = 500_000L; + when(mIrs.getConsumptionLimitLocked()).thenReturn(consumptionLimit); Ledger ledger = mScribeUnderTest.getLedgerLocked(TEST_USER_ID, TEST_PACKAGE); ledger.recordTransaction(new Ledger.Transaction(0, 1000L, 1, null, 2000, 0)); @@ -119,8 +120,13 @@ public class ScribeTest { mScribeUnderTest.setConsumptionLimitLocked(consumptionLimit); mScribeUnderTest.adjustRemainingConsumableNarcsLocked( remainingConsumableNarcs - consumptionLimit); - mScribeUnderTest.writeImmediatelyForTesting(); + assertEquals(lastReclamationTime, mScribeUnderTest.getLastReclamationTimeLocked()); + assertEquals(remainingConsumableNarcs, + mScribeUnderTest.getRemainingConsumableNarcsLocked()); + assertEquals(consumptionLimit, mScribeUnderTest.getSatiatedConsumptionLimitLocked()); + + mScribeUnderTest.writeImmediatelyForTesting(); mScribeUnderTest.loadFromDiskLocked(); assertEquals(lastReclamationTime, mScribeUnderTest.getLastReclamationTimeLocked()); diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 152f3b3abd13..e3be3a792549 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -64,6 +64,7 @@ android_test { "testng", "junit", "platform-compat-test-rules", + "ActivityContext", ], aidl: { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java index 1f016fb6f017..56c51507606f 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -28,6 +28,8 @@ import static com.android.internal.accessibility.AccessibilityShortcutController import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -61,10 +63,12 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import com.android.compatibility.common.util.TestUtils; +import com.android.internal.compat.IPlatformCompat; import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener; import com.android.server.accessibility.magnification.FullScreenMagnificationController; import com.android.server.accessibility.magnification.MagnificationController; +import com.android.server.accessibility.magnification.MagnificationProcessor; import com.android.server.accessibility.magnification.WindowMagnificationManager; import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.pm.UserManagerInternal; @@ -185,7 +189,7 @@ public class AccessibilityManagerServiceTest { mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState); } - private void setupAccessibilityServiceConnection() { + private void setupAccessibilityServiceConnection(int serviceInfoFlag) { final AccessibilityUserState userState = mA11yms.mUserStates.get( mA11yms.getCurrentUserIdLocked()); when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo); @@ -193,7 +197,12 @@ public class AccessibilityManagerServiceTest { mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class); when(mMockBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient); + when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class)); + when(mMockSystemSupport.getMagnificationProcessor()).thenReturn( + mock(MagnificationProcessor.class)); mTestableContext.addMockService(COMPONENT_NAME, mMockBinder); + + mMockServiceInfo.flags = serviceInfoFlag; mAccessibilityServiceConnection = new AccessibilityServiceConnection( userState, mTestableContext, @@ -256,7 +265,7 @@ public class AccessibilityManagerServiceTest { @SmallTest @Test public void testOnSystemActionsChanged() throws Exception { - setupAccessibilityServiceConnection(); + setupAccessibilityServiceConnection(0); final AccessibilityUserState userState = mA11yms.mUserStates.get( mA11yms.getCurrentUserIdLocked()); @@ -376,7 +385,7 @@ public class AccessibilityManagerServiceTest { @SmallTest @Test public void testOnClientChange_boundServiceCanControlMagnification_requestConnection() { - setupAccessibilityServiceConnection(); + setupAccessibilityServiceConnection(0); when(mMockSecurityPolicy.canControlMagnification(any())).thenReturn(true); // Invokes client change to trigger onUserStateChanged. @@ -385,6 +394,29 @@ public class AccessibilityManagerServiceTest { verify(mMockWindowMagnificationMgr).requestConnection(true); } + @Test + public void testUnbindIme_whenServiceUnbinds() { + setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR); + mAccessibilityServiceConnection.unbindLocked(); + verify(mMockSystemSupport, atLeastOnce()).unbindImeLocked(mAccessibilityServiceConnection); + } + + @Test + public void testUnbindIme_whenServiceCrashed() { + setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR); + mAccessibilityServiceConnection.binderDied(); + verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection); + } + + @Test + public void testUnbindIme_whenServiceStopsRequestingIme() { + setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR); + doCallRealMethod().when(mMockServiceInfo).updateDynamicallyConfigurableProperties( + any(IPlatformCompat.class), any(AccessibilityServiceInfo.class)); + mAccessibilityServiceConnection.setServiceInfo(new AccessibilityServiceInfo()); + verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection); + } + public static class FakeInputFilter extends AccessibilityInputFilter { FakeInputFilter(Context context, AccessibilityManagerService service) { diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java index 4de15c87dcc1..928c76d07d7c 100644 --- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java @@ -330,11 +330,12 @@ public class JobStoreTest { @Test public void testPriorityPersisted() throws Exception { - final JobInfo.Builder b = new Builder(92, mComponent) + final JobInfo job = new Builder(92, mComponent) .setOverrideDeadline(5000) .setPriority(JobInfo.PRIORITY_MIN) - .setPersisted(true); - final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); + .setPersisted(true) + .build(); + final JobStatus js = JobStatus.createFromJobInfo(job, SOME_UID, null, -1, null); mTaskStoreUnderTest.add(js); waitForPendingIo(); @@ -342,7 +343,7 @@ public class JobStoreTest { mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); final JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); assertEquals("Priority not correctly persisted.", - JobInfo.PRIORITY_MIN, loaded.getEffectivePriority()); + JobInfo.PRIORITY_MIN, job.getPriority()); } /** 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/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java index 3cb5d5f92810..ce322f7cb6e6 100644 --- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java @@ -20,6 +20,7 @@ import static org.testng.Assert.assertThrows; import android.Manifest; import android.app.ActivityManager; import android.app.ActivityManagerInternal; +import android.app.ActivityOptions; import android.app.AppOpsManager; import android.app.IApplicationThread; import android.app.admin.DevicePolicyManagerInternal; @@ -46,6 +47,7 @@ import android.permission.PermissionManager; import android.platform.test.annotations.Presubmit; import android.util.SparseArray; +import com.android.activitycontext.ActivityContext; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.util.FunctionalUtils.ThrowingSupplier; import com.android.server.LocalServices; @@ -240,7 +242,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PRIMARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -265,7 +269,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PRIMARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -292,7 +298,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -319,7 +327,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -344,7 +354,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -369,7 +381,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -396,7 +410,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -440,7 +456,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -465,7 +483,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, new ComponentName(PACKAGE_TWO, "test"), UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -490,7 +510,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, new ComponentName(PACKAGE_TWO, "test"), UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -515,7 +537,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(SECONDARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -540,7 +564,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(SECONDARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -564,7 +590,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PRIMARY_USER).getIdentifier(), - true); + true, + /* targetTask */ null, + /* options */ null); verify(mActivityTaskManagerInternal) .startActivityAsUser( @@ -578,6 +606,44 @@ public class CrossProfileAppsServiceImplTest { eq(PRIMARY_USER)); } + @Test + public void startActivityAsUser_sameTask_fromProfile_success() throws Exception { + mTestInjector.setCallingUserId(PROFILE_OF_PRIMARY_USER); + + Bundle options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(); + IBinder result = ActivityContext.getWithContext(activity -> { + try { + IBinder targetTask = activity.getActivityToken(); + mCrossProfileAppsServiceImpl.startActivityAsUser( + mIApplicationThread, + PACKAGE_ONE, + FEATURE_ID, + ACTIVITY_COMPONENT, + UserHandle.of(PRIMARY_USER).getIdentifier(), + true, + targetTask, + options); + return targetTask; + } catch (Exception re) { + return null; + } + }); + if (result == null) { + throw new Exception(); + } + + verify(mActivityTaskManagerInternal) + .startActivityAsUser( + nullable(IApplicationThread.class), + eq(PACKAGE_ONE), + eq(FEATURE_ID), + any(Intent.class), + eq(result), + anyInt(), + eq(options), + eq(PRIMARY_USER)); + } + private void mockAppsInstalled(String packageName, int user, boolean installed) { when(mPackageManagerInternal.getPackageInfo( eq(packageName), 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/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index c7b5547170d0..06b711251c0f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -316,7 +316,8 @@ public final class UserManagerTest { asHandle(currentUser)); try { assertThat(mUserManager.removeUserWhenPossible(user1.getUserHandle(), - /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR); + /* overrideDevicePolicy= */ false)) + .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION); } finally { mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false, asHandle(currentUser)); @@ -353,7 +354,8 @@ public final class UserManagerTest { @Test public void testRemoveUserWhenPossible_systemUserReturnsError() throws Exception { assertThat(mUserManager.removeUserWhenPossible(UserHandle.SYSTEM, - /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR); + /* overrideDevicePolicy= */ false)) + .isEqualTo(UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER); assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue(); } @@ -363,7 +365,8 @@ public final class UserManagerTest { public void testRemoveUserWhenPossible_invalidUserReturnsError() throws Exception { assertThat(hasUser(Integer.MAX_VALUE)).isFalse(); assertThat(mUserManager.removeUserWhenPossible(UserHandle.of(Integer.MAX_VALUE), - /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR); + /* overrideDevicePolicy= */ false)) + .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND); } @MediumTest diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java index 1442f1c82d42..83139b02430a 100644 --- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java @@ -23,9 +23,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.eq; @@ -37,6 +39,7 @@ import static org.mockito.Mockito.when; import android.Manifest; import android.app.ActivityManagerInternal; import android.app.StatusBarManager; +import android.compat.testing.PlatformCompatChangeRule; import android.content.ComponentName; import android.content.Intent; import android.content.om.IOverlayManager; @@ -62,10 +65,13 @@ import com.android.server.LocalServices; import com.android.server.policy.GlobalActionsProvider; import com.android.server.wm.ActivityTaskManagerInternal; +import libcore.junit.util.compat.CoreCompatChangeRule; + import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; @@ -73,6 +79,7 @@ import org.mockito.ArgumentMatcher; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; @RunWith(JUnit4.class) public class StatusBarManagerServiceTest { @@ -88,6 +95,9 @@ public class StatusBarManagerServiceTest { public final TestableContext mContext = new NoBroadcastContextWrapper(InstrumentationRegistry.getContext()); + @Rule + public TestRule mCompatChangeRule = new PlatformCompatChangeRule(); + @Mock private ActivityTaskManagerInternal mActivityTaskManagerInternal; @Mock @@ -127,6 +137,7 @@ public class StatusBarManagerServiceTest { when(mMockStatusBar.asBinder()).thenReturn(mMockStatusBar); when(mApplicationInfo.loadLabel(any())).thenReturn(APP_NAME); + mockHandleIncomingUser(); mStatusBarManagerService = new StatusBarManagerService(mContext); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); @@ -142,6 +153,80 @@ public class StatusBarManagerServiceTest { } @Test + @CoreCompatChangeRule.EnableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeEnabled_OKCall() throws RemoteException { + int user = 0; + mockEverything(user); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.EnableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeEnabled_differentPackage_fail() throws RemoteException { + when(mPackageManagerInternal.getPackageUid(TEST_PACKAGE, 0L, mContext.getUserId())) + .thenReturn(Binder.getCallingUid() + 1); + try { + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, 0); + fail("Should cause security exception"); + } catch (SecurityException e) { } + verify(mMockStatusBar, never()).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.EnableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeEnabled_notCurrentUser_fail() throws RemoteException { + mockUidCheck(); + int user = 0; + mockCurrentUserCheck(user); + try { + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user + 1); + fail("Should cause illegal argument exception"); + } catch (IllegalArgumentException e) { } + + // Do not call into SystemUI + verify(mMockStatusBar, never()).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.DisableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeDisabled_pass() throws RemoteException { + int user = 0; + mockEverything(user); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.DisableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeDisabled_differentPackage_pass() throws RemoteException { + when(mPackageManagerInternal.getPackageUid(TEST_PACKAGE, 0L, mContext.getUserId())) + .thenReturn(Binder.getCallingUid() + 1); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, 0); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.DisableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeDisabled_notCurrentUser_pass() throws RemoteException { + mockUidCheck(); + int user = 0; + mockCurrentUserCheck(user); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user + 1); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test public void testHandleIncomingUserCalled() { int fakeUser = 17; try { @@ -252,7 +337,7 @@ public class StatusBarManagerServiceTest { mockCurrentUserCheck(user); IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(null); Callback callback = new Callback(); @@ -272,7 +357,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -294,7 +379,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -318,7 +403,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -342,7 +427,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -607,23 +692,12 @@ public class StatusBarManagerServiceTest { public void testSetNavBarMode_invalidInputThrowsError() throws RemoteException { int navBarModeInvalid = -1; - assertThrows(UnsupportedOperationException.class, + assertThrows(IllegalArgumentException.class, () -> mStatusBarManagerService.setNavBarMode(navBarModeInvalid)); verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt()); } @Test - public void testSetNavBarMode_noOverlayManagerDoesNotEnable() throws RemoteException { - mOverlayManager = null; - int navBarModeKids = StatusBarManager.NAV_BAR_MODE_KIDS; - - mStatusBarManagerService.setNavBarMode(navBarModeKids); - - assertEquals(navBarModeKids, mStatusBarManagerService.getNavBarMode()); - verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt()); - } - - @Test public void testSetNavBarMode_noPackageDoesNotEnable() throws Exception { mContext.setMockPackageManager(mPackageManager); when(mPackageManager.getPackageInfo(anyString(), @@ -641,7 +715,7 @@ public class StatusBarManagerServiceTest { } private void mockUidCheck(String packageName) { - when(mPackageManagerInternal.getPackageUid(eq(packageName), anyInt(), anyInt())) + when(mPackageManagerInternal.getPackageUid(eq(packageName), anyLong(), anyInt())) .thenReturn(Binder.getCallingUid()); } @@ -667,7 +741,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(componentName)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(componentName, Binder.getCallingUid(), user)).thenReturn( @@ -679,6 +753,15 @@ public class StatusBarManagerServiceTest { PROCESS_STATE_TOP); } + private void mockHandleIncomingUser() { + when(mActivityManagerInternal.handleIncomingUser(anyInt(), anyInt(), anyInt(), anyBoolean(), + anyInt(), anyString(), anyString())).thenAnswer( + (Answer<Integer>) invocation -> { + return invocation.getArgument(2); // same user + } + ); + } + private void mockEverything(int user) { mockUidCheck(); mockCurrentUserCheck(user); 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 1ce957d1e768..210d2faf44d6 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -62,7 +62,10 @@ import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.intThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -76,11 +79,13 @@ import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.ContextWrapper; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.content.pm.ResolveInfo; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Looper; @@ -118,6 +123,7 @@ import java.util.Random; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** * Unit test for AppStandbyController. @@ -421,8 +427,31 @@ public class AppStandbyControllerTests { pib.packageName = PACKAGE_BACKGROUND_LOCATION; packages.add(pib); - doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt()); + // Set up getInstalledPackagesAsUser(). + doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), + anyInt()); + + // Set up getInstalledPackagesAsUser() for "MATCH_ONLY_SYSTEM" + doReturn( + packages.stream().filter(pinfo -> pinfo.applicationInfo.isSystemApp()) + .collect(Collectors.toList()) + ).when(mockPm).getInstalledPackagesAsUser( + intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), + anyInt()); + + // Set up queryIntentActivitiesAsUser() + final ArrayList<ResolveInfo> systemFrontDoorActivities = new ArrayList<>(); + final ResolveInfo frontDoorActivity = new ResolveInfo(); + frontDoorActivity.activityInfo = new ActivityInfo(); + frontDoorActivity.activityInfo.packageName = pis.packageName; + systemFrontDoorActivities.add(frontDoorActivity); + doReturn(systemFrontDoorActivities).when(mockPm) + .queryIntentActivitiesAsUser(any(Intent.class), + intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), + anyInt()); + + // Set up other APIs. try { for (int i = 0; i < packages.size(); ++i) { PackageInfo pkg = packages.get(i); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java index 50151bfb7191..46b47f4dcfdd 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java @@ -88,7 +88,7 @@ public class PermissionHelperTest extends UiServiceTestCase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mPermissionHelper = new PermissionHelper(mPmi, mPackageManager, mPermManager, true); + mPermissionHelper = new PermissionHelper(mPmi, mPackageManager, mPermManager, true, false); PackageInfo testPkgInfo = new PackageInfo(); testPkgInfo.requestedPermissions = new String[]{ Manifest.permission.POST_NOTIFICATIONS }; when(mPackageManager.getPackageInfo(anyString(), anyLong(), anyInt())) @@ -100,7 +100,7 @@ public class PermissionHelperTest extends UiServiceTestCase { public void testMethodsThrowIfMigrationDisabled() throws IllegalAccessException, InvocationTargetException { PermissionHelper permHelper = - new PermissionHelper(mPmi, mPackageManager, mPermManager, false); + new PermissionHelper(mPmi, mPackageManager, mPermManager, false, false); Method[] allMethods = PermissionHelper.class.getDeclaredMethods(); for (Method method : allMethods) { @@ -302,6 +302,26 @@ public class PermissionHelperTest extends UiServiceTestCase { } @Test + public void testSetNotificationPermission_pkgPerm_grantedByDefaultPermSet_allUserSet() + throws Exception { + mPermissionHelper = new PermissionHelper(mPmi, mPackageManager, mPermManager, true, true); + when(mPmi.checkPermission(anyString(), anyString(), anyInt())) + .thenReturn(PERMISSION_DENIED); + when(mPermManager.getPermissionFlags(anyString(), + eq(Manifest.permission.POST_NOTIFICATIONS), + anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT); + PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission( + "pkg", 10, true, false); + + mPermissionHelper.setNotificationPermission(pkgPerm); + verify(mPermManager).grantRuntimePermission( + "pkg", Manifest.permission.POST_NOTIFICATIONS, 10); + verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS, + FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_REVIEW_REQUIRED, + FLAG_PERMISSION_USER_SET, true, 10); + } + + @Test public void testSetNotificationPermission_revokeUserSet() throws Exception { when(mPmi.checkPermission(anyString(), anyString(), anyInt())) .thenReturn(PERMISSION_GRANTED); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index 31be33e98363..fd1536c5c0f1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -43,6 +43,7 @@ import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER; +import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -1611,6 +1612,35 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + public void testAddAutomaticZenRule_beyondSystemLimit() { + for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) { + ScheduleInfo si = new ScheduleInfo(); + si.startHour = i; + AutomaticZenRule zenRule = new AutomaticZenRule("name" + i, + null, + new ComponentName("android", "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(si), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test"); + assertNotNull(id); + } + try { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName("android", "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test"); + fail("allowed too many rules to be created"); + } catch (IllegalArgumentException e) { + // yay + } + + } + + @Test public void testAddAutomaticZenRule_CA() { AutomaticZenRule zenRule = new AutomaticZenRule("name", null, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index d4d8b86850c6..7689e08bc3f3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -256,6 +256,14 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity); verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity)); + + // If an activity is removed immediately before visibility update, it should cancel too. + final ActivityRecord removedImm = new ActivityBuilder(mAtm).setCreateTask(true).build(); + clearInvocations(mLaunchObserver); + onActivityLaunched(removedImm); + removedImm.removeImmediately(); + // Verify any() instead of proto because the field of record may be changed. + verifyAsync(mLaunchObserver).onActivityLaunchCancelled(any()); } @Test @@ -299,15 +307,16 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { @Test public void testOnReportFullyDrawn() { // Create an invisible event that should be cancelled after the next event starts. - onActivityLaunched(mTrampolineActivity); - mTrampolineActivity.mVisibleRequested = false; + final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true).build(); + onActivityLaunched(prev); + prev.mVisibleRequested = false; mActivityOptions = ActivityOptions.makeBasic(); mActivityOptions.setSourceInfo(SourceInfo.TYPE_LAUNCHER, SystemClock.uptimeMillis() - 10); onIntentStarted(mTopActivity.intent); notifyActivityLaunched(START_SUCCESS, mTopActivity); verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt()); - verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity)); + verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(prev)); // The activity reports fully drawn before windows drawn, then the fully drawn event will // be pending (see {@link WindowingModeTransitionInfo#pendingFullyDrawn}). diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 40ab8eb70c04..f8e15041f8f4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2184,11 +2184,17 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testSupportsPictureInPicture() { + final Task task = new TaskBuilder(mSupervisor) + .setDisplay(mDisplayContent).build(); final ActivityRecord activity = new ActivityBuilder(mAtm) - .setCreateTask(true) + .setTask(task) .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE) .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE) .build(); + spyOn(mDisplayContent); + spyOn(mDisplayContent.mDwpcHelper); + doReturn(true).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( + WINDOWING_MODE_PINNED); // Device not supports PIP mAtm.mSupportsPictureInPicture = false; @@ -2201,6 +2207,15 @@ public class ActivityRecordTests extends WindowTestsBase { // Activity not supports PIP activity.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE; assertFalse(activity.supportsPictureInPicture()); + + // Activity supports PIP + activity.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE; + assertTrue(activity.supportsPictureInPicture()); + + // Display not supports PIP + doReturn(false).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( + WINDOWING_MODE_PINNED); + assertFalse(activity.supportsPictureInPicture()); } @Test @@ -3086,11 +3101,11 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen + mDisplayContent.updateImeInputAndControlTarget(app); + assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.getInsetsState().addSource(imeSource); app.getInsetsState().setSourceVisible(ITYPE_IME, true); - mDisplayContent.updateImeInputAndControlTarget(app); - assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index c21a5b6ff7ea..92550a3107d5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -30,7 +30,10 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.hardware.HardwareBuffer; import android.platform.test.annotations.Presubmit; +import android.window.BackEvent; import android.window.BackNavigationInfo; +import android.window.IOnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; import android.window.TaskSnapshot; import org.junit.Before; @@ -42,15 +45,19 @@ import org.junit.runner.RunWith; public class BackNavigationControllerTests extends WindowTestsBase { private BackNavigationController mBackNavigationController; + private IOnBackInvokedCallback mOnBackInvokedCallback; @Before public void setUp() throws Exception { mBackNavigationController = new BackNavigationController(); + mOnBackInvokedCallback = createBackCallback(); } @Test public void backTypeHomeWhenBackToLauncher() { Task task = createTopTaskWithActivity(); + registerSystemOnBackInvokedCallback(); + BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(task, new StubTransaction()); assertThat(backNavigationInfo).isNotNull(); @@ -63,6 +70,8 @@ public class BackNavigationControllerTests extends WindowTestsBase { Task taskA = createTask(mDefaultDisplay); createActivityRecord(taskA); Task task = createTopTaskWithActivity(); + registerSystemOnBackInvokedCallback(); + BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(task, new StubTransaction()); assertThat(backNavigationInfo).isNotNull(); @@ -75,6 +84,8 @@ public class BackNavigationControllerTests extends WindowTestsBase { Task task = createTopTaskWithActivity(); mAtm.setFocusedTask(task.mTaskId, createAppWindow(task, FIRST_APPLICATION_WINDOW, "window").mActivityRecord); + registerSystemOnBackInvokedCallback(); + BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(task, new StubTransaction()); assertThat(backNavigationInfo).isNotNull(); @@ -89,6 +100,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { public void backNavInfoFullyPopulated() { Task task = createTopTaskWithActivity(); createAppWindow(task, FIRST_APPLICATION_WINDOW, "window"); + registerSystemOnBackInvokedCallback(); // We need a mock screenshot so TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController(); @@ -104,6 +116,30 @@ public class BackNavigationControllerTests extends WindowTestsBase { assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull(); } + @Test + public void preparesForBackToHome() { + Task task = createTopTaskWithActivity(); + ActivityRecord activity = task.getTopActivity(false, false); + registerSystemOnBackInvokedCallback(); + + BackNavigationInfo backNavigationInfo = + mBackNavigationController.startBackNavigation(task, new StubTransaction()); + assertThat(typeToString(backNavigationInfo.getType())) + .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME)); + } + + @Test + public void backTypeCallback() { + Task task = createTopTaskWithActivity(); + ActivityRecord activity = task.getTopActivity(false, false); + registerApplicationOnBackInvokedCallback(); + + BackNavigationInfo backNavigationInfo = + mBackNavigationController.startBackNavigation(task, new StubTransaction()); + assertThat(typeToString(backNavigationInfo.getType())) + .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK)); + } + @NonNull private TaskSnapshotController createMockTaskSnapshotController() { TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class); @@ -126,4 +162,30 @@ public class BackNavigationControllerTests extends WindowTestsBase { mAtm.setFocusedTask(task.mTaskId, record); return task; } + + private void registerSystemOnBackInvokedCallback() { + mWm.getFocusedWindowLocked().setOnBackInvokedCallback( + mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_SYSTEM); + } + + private void registerApplicationOnBackInvokedCallback() { + mWm.getFocusedWindowLocked().setOnBackInvokedCallback( + mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT); + } + + private IOnBackInvokedCallback createBackCallback() { + return new IOnBackInvokedCallback.Stub() { + @Override + public void onBackStarted() { } + + @Override + public void onBackProgressed(BackEvent backEvent) { } + + @Override + public void onBackCancelled() { } + + @Override + public void onBackInvoked() { } + }; + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 8e990f7763c4..40b460157bc2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1102,6 +1102,21 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } + @UseTestDisplay(addWindows = W_ACTIVITY) + @Test + public void testComputeImeParent_inputTargetNotUpdate() throws Exception { + WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1"); + WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2"); + doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); + mDisplayContent.setImeLayeringTarget(app1); + mDisplayContent.setImeInputTarget(app1); + assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent()); + mDisplayContent.setImeLayeringTarget(app2); + // Expect null means no change IME parent when the IME layering target not yet + // request IME to be the input target. + assertNull(mDisplayContent.computeImeParent()); + } + @Test public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { final DisplayContent dc = createNewDisplay(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java index 6e11d8cf23e1..f9689990c5e8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java @@ -16,13 +16,18 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; +import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.os.UserHandle; @@ -37,6 +42,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.List; +import java.util.Set; /** * Tests for the {@link DisplayWindowPolicyControllerHelper} class. @@ -113,6 +119,39 @@ public class DisplayWindowPolicyControllerHelperTests extends WindowTestsBase { return activity; } + @Test + public void testIsWindowingModeSupported_noController_returnTrueForAnyWindowingMode() { + doReturn(null).when(mWm.mDisplayManagerInternal) + .getDisplayWindowPolicyController(anyInt()); + mSecondaryDisplay = createNewDisplay(); + assertFalse(mSecondaryDisplay.mDwpcHelper.hasController()); + + assertTrue(mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_PINNED)); + assertTrue( + mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_FULLSCREEN)); + } + + @Test + public void testIsWindowingModeSupported_withoutSettingSupportedMode_returnFalse() { + assertFalse(mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_PINNED)); + } + + @Test + public void testIsWindowingModeSupported_withoutSupportedMode_defaultSupportFullScreen() { + assertTrue( + mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_FULLSCREEN)); + } + + @Test + public void testIsWindowingModeSupported_setPinnedMode_returnTrue() { + Set<Integer> supportedWindowingMode = new ArraySet<>(); + supportedWindowingMode.add(WINDOWING_MODE_PINNED); + + mDwpc.setSupportedWindowingModes(supportedWindowingMode); + + assertTrue(mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_PINNED)); + } + private class TestDisplayWindowPolicyController extends DisplayWindowPolicyController { ComponentName mTopActivity = null; @@ -120,7 +159,8 @@ public class DisplayWindowPolicyControllerHelperTests extends WindowTestsBase { ArraySet<Integer> mRunningUids = new ArraySet<>(); @Override - public boolean canContainActivities(@NonNull List<ActivityInfo> activities) { + public boolean canContainActivities(@NonNull List<ActivityInfo> activities, + @WindowConfiguration.WindowingMode int windowingMode) { return false; } 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/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 636c6bc77e0a..9304761fc1c9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -259,6 +259,20 @@ public class TaskTests extends WindowTestsBase { } @Test + public void testPerformClearTop() { + final Task task = createTask(mDisplayContent); + final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); + final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build(); + // Detach from process so the activities can be removed from hierarchy when finishing. + activity1.detachFromProcess(); + activity2.detachFromProcess(); + assertNull(task.performClearTop(activity1, 0 /* launchFlags */)); + assertFalse(task.hasChild()); + // In real case, the task should be preserved for adding new activity. + assertTrue(task.isAttached()); + } + + @Test public void testRemoveChildForOverlayTask() { final Task task = createTask(mDisplayContent); final int taskId = task.mTaskId; diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index 7dfb5aef7fe7..4f35d55bc2d0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -44,7 +44,7 @@ public class TestIWindow extends IWindow.Stub { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars, - int displayId) throws RemoteException { + int displayId, int seqId) throws RemoteException { } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index c4547f654c33..7e5d017e2bc4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -692,7 +692,8 @@ public class TransitionTests extends WindowTestsBase { statusBar.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; final SurfaceControl.Transaction postDrawTransaction = mock(SurfaceControl.Transaction.class); - final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction); + final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction, + Integer.MAX_VALUE); assertFalse(layoutNeeded); transactionCommittedListener.onTransactionCommitted(); @@ -742,7 +743,7 @@ public class TransitionTests extends WindowTestsBase { player.finish(); // The controller should be cleared if the target windows are drawn. - statusBar.finishDrawing(mWm.mTransactionFactory.get()); + statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE); statusBar.setOrientationChanging(false); assertNull(mDisplayContent.getAsyncRotationController()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java index 7d2e9bf26b01..ea18e58fe999 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java @@ -45,6 +45,7 @@ import android.view.InsetsVisibilities; import android.view.WindowInsets; import android.view.WindowLayout; import android.view.WindowManager; +import android.window.ClientWindowFrames; import androidx.test.filters.SmallTest; @@ -71,9 +72,7 @@ public class WindowLayoutTests { private static final Insets WATERFALL_INSETS = Insets.of(6, 0, 12, 0); private final WindowLayout mWindowLayout = new WindowLayout(); - private final Rect mDisplayFrame = new Rect(); - private final Rect mParentFrame = new Rect(); - private final Rect mFrame = new Rect(); + private final ClientWindowFrames mOutFrames = new ClientWindowFrames(); private WindowManager.LayoutParams mAttrs; private InsetsState mState; @@ -108,7 +107,7 @@ public class WindowLayoutTests { private void computeFrames() { mWindowLayout.computeFrames(mAttrs, mState, mDisplayCutoutSafe, mWindowBounds, mWindowingMode, mRequestedWidth, mRequestedHeight, mRequestedVisibilities, - mAttachedWindowFrame, mCompatScale, mDisplayFrame, mParentFrame, mFrame); + mAttachedWindowFrame, mCompatScale, mOutFrames); } private void addDisplayCutout() { @@ -146,9 +145,9 @@ public class WindowLayoutTests { public void defaultParams() { computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); } @Test @@ -157,9 +156,9 @@ public class WindowLayoutTests { mRequestedHeight = UNSPECIFIED_LENGTH; computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); } @Test @@ -173,9 +172,9 @@ public class WindowLayoutTests { mAttrs.gravity = Gravity.LEFT | Gravity.TOP; computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame); - assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); + assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mOutFrames.frame); } @Test @@ -186,9 +185,12 @@ public class WindowLayoutTests { mRequestedHeight = UNSPECIFIED_LENGTH; computeFrames(); - assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mParentFrame); - assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mFrame); + assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, + mOutFrames.displayFrame); + assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, + mOutFrames.parentFrame); + assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, + mOutFrames.frame); } @Test @@ -196,9 +198,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(WindowInsets.Type.statusBars()); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame); } @Test @@ -206,9 +208,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(WindowInsets.Type.navigationBars()); computeFrames(); - assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mParentFrame); - assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mFrame); + assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); + assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); } @Test @@ -216,9 +218,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetByTopBottom(0, 0, mDisplayFrame); - assertInsetByTopBottom(0, 0, mParentFrame); - assertInsetByTopBottom(0, 0, mFrame); + assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); + assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); + assertInsetByTopBottom(0, 0, mOutFrames.frame); } @Test @@ -226,9 +228,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsSides(WindowInsets.Side.all()); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); } @Test @@ -236,9 +238,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsSides(WindowInsets.Side.TOP); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame); } @Test @@ -246,9 +248,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsSides(0); computeFrames(); - assertInsetByTopBottom(0, 0, mDisplayFrame); - assertInsetByTopBottom(0, 0, mParentFrame); - assertInsetByTopBottom(0, 0, mFrame); + assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); + assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); + assertInsetByTopBottom(0, 0, mOutFrames.frame); } @Test @@ -257,9 +259,9 @@ public class WindowLayoutTests { mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false); computeFrames(); - assertInsetByTopBottom(0, 0, mDisplayFrame); - assertInsetByTopBottom(0, 0, mParentFrame); - assertInsetByTopBottom(0, 0, mFrame); + assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); + assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); + assertInsetByTopBottom(0, 0, mOutFrames.frame); } @Test @@ -269,9 +271,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsIgnoringVisibility(true); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); } @Test @@ -282,9 +284,9 @@ public class WindowLayoutTests { mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME; computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mParentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.frame); } @Test @@ -295,11 +297,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0, - mDisplayFrame); + mOutFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0, - mParentFrame); + mOutFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0, - mFrame); + mOutFrames.frame); } @Test @@ -310,11 +312,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mDisplayFrame); + mOutFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mParentFrame); + mOutFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mFrame); + mOutFrames.frame); } @Test @@ -325,9 +327,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mDisplayFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mParentFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame); } @Test @@ -342,9 +344,9 @@ public class WindowLayoutTests { mAttrs.privateFlags |= PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; computeFrames(); - assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayFrame); - assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mParentFrame); - assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mFrame); + assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.displayFrame); + assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.parentFrame); + assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mOutFrames.frame); } @Test @@ -357,11 +359,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mDisplayFrame); + mOutFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mParentFrame); + mOutFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mFrame); + mOutFrames.frame); } @Test @@ -371,9 +373,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mDisplayFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mParentFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame); } @Test @@ -384,11 +386,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mDisplayFrame); + mOutFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mParentFrame); + mOutFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mFrame); + mOutFrames.frame); } @Test @@ -398,8 +400,8 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetByTopBottom(0, 0, mDisplayFrame); - assertInsetByTopBottom(0, 0, mParentFrame); - assertInsetByTopBottom(0, 0, mFrame); + assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); + assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); + assertInsetByTopBottom(0, 0, mOutFrames.frame); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index e4f691b338e1..6a3aa78fc632 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -504,7 +504,7 @@ public class WindowStateTests extends WindowTestsBase { assertTrue(win.useBLASTSync()); final SurfaceControl.Transaction drawT = new StubTransaction(); win.prepareDrawHandlers(); - assertTrue(win.finishDrawing(drawT)); + assertTrue(win.finishDrawing(drawT, Integer.MAX_VALUE)); assertEquals(drawT, handledT[0]); assertFalse(win.useBLASTSync()); @@ -693,7 +693,7 @@ public class WindowStateTests extends WindowTestsBase { doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */, anyBoolean() /* reportDraw */, any() /* mergedConfig */, anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */, - anyInt() /* displayId */); + anyInt() /* displayId */, anyInt() /* seqId */); } catch (RemoteException ignored) { } win.reportResized(); @@ -820,7 +820,6 @@ public class WindowStateTests extends WindowTestsBase { @Test public void testHasActiveVisibleWindow() { final int uid = ActivityBuilder.DEFAULT_FAKE_UID; - mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid); app.mActivityRecord.setVisible(false); @@ -848,6 +847,11 @@ public class WindowStateTests extends WindowTestsBase { // Make the application overlay window visible. It should be a valid active visible window. overlay.onSurfaceShownChanged(true); assertTrue(mAtm.hasActiveVisibleWindow(uid)); + + // The number of windows should be independent of the existence of uid state. + mAtm.mActiveUids.onUidInactive(uid); + mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); + assertTrue(mAtm.mActiveUids.hasNonAppVisibleWindow(uid)); } @UseTestDisplay(addWindows = W_ACTIVITY) @@ -945,6 +949,46 @@ public class WindowStateTests extends WindowTestsBase { assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); } + @Test + public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { + final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); + final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW, + ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2"); + final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow"); + spyOn(imeWindow); + doReturn(true).when(imeWindow).isVisible(); + mDisplayContent.mInputMethodWindow = imeWindow; + + final InsetsStateController controller = mDisplayContent.getInsetsStateController(); + controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null); + + // Simulate app2 in multi-window mode is going to background to switch to the fullscreen + // app which requests IME with updating all windows Insets State when IME is above app. + app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true; + mDisplayContent.setImeLayeringTarget(app); + mDisplayContent.setImeInputTarget(app); + assertTrue(mDisplayContent.shouldImeAttachedToApp()); + controller.getImeSourceProvider().scheduleShowImePostLayout(app); + controller.getImeSourceProvider().getSource().setVisible(true); + controller.updateAboveInsetsState(false); + + // Expect app windows behind IME can receive IME insets visible, + // but not for app2 in background. + assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); + assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); + + // Simulate app plays closing transition to app2. + // And app2 is now IME layering target but not yet to be the IME input target. + mDisplayContent.setImeLayeringTarget(app2); + app.mActivityRecord.commitVisibility(false, false); + assertTrue(app.mActivityRecord.mLastImeShown); + assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); + + // Verify the IME insets is still visible on app, but not for app2 during task switching. + assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); + assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); + } + @UseTestDisplay(addWindows = {W_ACTIVITY}) @Test public void testUpdateImeControlTargetWhenLeavingMultiWindow() { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index a597fc69a340..398889213ce5 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -23,6 +23,25 @@ import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_MICROPH import static android.service.voice.HotwordDetectionService.INITIALIZATION_STATUS_UNKNOWN; import static android.service.voice.HotwordDetectionService.KEY_INITIALIZATION_STATUS; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_ERROR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_SUCCESS; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_NO_VALUE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_OVER_MAX_CUSTOM_VALUE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_UPDATE_STATE_AFTER_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED; import static com.android.server.voiceinteraction.SoundTriggerSessionPermissionsDecorator.enforcePermissionForPreflight; import android.annotation.NonNull; @@ -48,6 +67,7 @@ import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SharedMemory; +import android.provider.DeviceConfig; import android.service.voice.HotwordDetectedResult; import android.service.voice.HotwordDetectionService; import android.service.voice.HotwordDetector; @@ -91,33 +111,56 @@ final class HotwordDetectionConnection { private static final String TAG = "HotwordDetectionConnection"; static final boolean DEBUG = false; + private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds"; // TODO: These constants need to be refined. - private static final long VALIDATION_TIMEOUT_MILLIS = 3000; + private static final long VALIDATION_TIMEOUT_MILLIS = 4000; private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000; private static final Duration MAX_UPDATE_TIMEOUT_DURATION = Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS); private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour + /** + * Time after which each HotwordDetectionService process is stopped and replaced by a new one. + * 0 indicates no restarts. + */ + private static final int RESTART_PERIOD_SECONDS = + DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION, + KEY_RESTART_PERIOD_IN_SECONDS, 0); private static final int MAX_ISOLATED_PROCESS_NUMBER = 10; + // Hotword metrics + private static final int METRICS_INIT_UNKNOWN_TIMEOUT = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_TIMEOUT; + private static final int METRICS_INIT_UNKNOWN_NO_VALUE = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_NO_VALUE; + private static final int METRICS_INIT_UNKNOWN_OVER_MAX_CUSTOM_VALUE = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_OVER_MAX_CUSTOM_VALUE; + private static final int METRICS_INIT_CALLBACK_STATE_ERROR = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_ERROR; + private static final int METRICS_INIT_CALLBACK_STATE_SUCCESS = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_SUCCESS; + private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool(); // TODO: This may need to be a Handler(looper) private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); + @Nullable private final ScheduledFuture<?> mCancellationTaskFuture; private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied; private final @NonNull ServiceConnectionFactory mServiceConnectionFactory; private final IHotwordRecognitionStatusCallback mCallback; + private final int mDetectorType; final Object mLock; final int mVoiceInteractionServiceUid; final ComponentName mDetectionComponentName; final int mUser; final Context mContext; + volatile HotwordDetectionServiceIdentity mIdentity; private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback; private Instant mLastRestartInstant; - private ScheduledFuture<?> mCancellationTaskFuture; + private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture; private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null; /** Identity used for attributing app ops when delivering data to the Interactor. */ @@ -133,7 +176,6 @@ final class HotwordDetectionConnection { private @NonNull ServiceConnection mRemoteHotwordDetectionService; private IBinder mAudioFlinger; private boolean mDebugHotwordLogging = false; - private final int mDetectorType; HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid, Identity voiceInteractorIdentity, ComponentName serviceName, int userId, @@ -163,14 +205,20 @@ final class HotwordDetectionConnection { mLastRestartInstant = Instant.now(); updateStateAfterProcessStart(options, sharedMemory); - // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait - // until the current session is closed. - mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> { - Slog.v(TAG, "Time to restart the process, TTL has passed"); - synchronized (mLock) { - restartProcessLocked(); - } - }, 30, 30, TimeUnit.MINUTES); + if (RESTART_PERIOD_SECONDS <= 0) { + mCancellationTaskFuture = null; + } else { + // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait + // until the current session is closed. + mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> { + Slog.v(TAG, "Time to restart the process, TTL has passed"); + synchronized (mLock) { + restartProcessLocked(); + HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType, + HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE); + } + }, RESTART_PERIOD_SECONDS, RESTART_PERIOD_SECONDS, TimeUnit.SECONDS); + } } private void initAudioFlingerLocked() { @@ -201,6 +249,8 @@ final class HotwordDetectionConnection { // We restart the process instead of simply sending over the new binder, to avoid race // conditions with audio reading in the service. restartProcessLocked(); + HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType, + HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED); } } @@ -220,26 +270,32 @@ final class HotwordDetectionConnection { future.complete(null); if (mUpdateStateAfterStartFinished.getAndSet(true)) { Slog.w(TAG, "call callback after timeout"); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_UPDATE_STATE_AFTER_TIMEOUT, + mVoiceInteractionServiceUid); return; } - int status = bundle != null ? bundle.getInt( - KEY_INITIALIZATION_STATUS, - INITIALIZATION_STATUS_UNKNOWN) - : INITIALIZATION_STATUS_UNKNOWN; - // Add the protection to avoid unexpected status - if (status > HotwordDetectionService.getMaxCustomInitializationStatus() - && status != INITIALIZATION_STATUS_UNKNOWN) { - status = INITIALIZATION_STATUS_UNKNOWN; - } + Pair<Integer, Integer> statusResultPair = getInitStatusAndMetricsResult(bundle); + int status = statusResultPair.first; + int initResultMetricsResult = statusResultPair.second; try { mCallback.onStatusReported(status); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + initResultMetricsResult); } catch (RemoteException e) { + // TODO: Add a new atom for RemoteException case, the error doesn't very + // correct here Slog.w(TAG, "Failed to report initialization status: " + e); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + METRICS_INIT_CALLBACK_STATE_ERROR); } } }; try { service.updateState(options, sharedMemory, statusCallback); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE, + mVoiceInteractionServiceUid); } catch (RemoteException e) { // TODO: (b/181842909) Report an error to voice interactor Slog.w(TAG, "Failed to updateState for HotwordDetectionService", e); @@ -254,8 +310,12 @@ final class HotwordDetectionConnection { } try { mCallback.onStatusReported(INITIALIZATION_STATUS_UNKNOWN); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + METRICS_INIT_UNKNOWN_TIMEOUT); } catch (RemoteException e) { Slog.w(TAG, "Failed to report initialization status UNKNOWN", e); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + METRICS_INIT_CALLBACK_STATE_ERROR); } } else if (err != null) { Slog.w(TAG, "Failed to update state: " + err); @@ -265,6 +325,23 @@ final class HotwordDetectionConnection { }); } + private static Pair<Integer, Integer> getInitStatusAndMetricsResult(Bundle bundle) { + if (bundle == null) { + return new Pair<>(INITIALIZATION_STATUS_UNKNOWN, METRICS_INIT_UNKNOWN_NO_VALUE); + } + int status = bundle.getInt(KEY_INITIALIZATION_STATUS, INITIALIZATION_STATUS_UNKNOWN); + if (status > HotwordDetectionService.getMaxCustomInitializationStatus() + && status != INITIALIZATION_STATUS_UNKNOWN) { + return new Pair<>(INITIALIZATION_STATUS_UNKNOWN, + METRICS_INIT_UNKNOWN_OVER_MAX_CUSTOM_VALUE); + } + // TODO: should guard against negative here + int metricsResult = status == INITIALIZATION_STATUS_UNKNOWN + ? METRICS_INIT_CALLBACK_STATE_ERROR + : METRICS_INIT_CALLBACK_STATE_SUCCESS; + return new Pair<>(status, metricsResult); + } + private boolean isBound() { synchronized (mLock) { return mRemoteHotwordDetectionService.isBound(); @@ -282,7 +359,9 @@ final class HotwordDetectionConnection { removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid()); } mIdentity = null; - mCancellationTaskFuture.cancel(/* may interrupt */ true); + if (mCancellationTaskFuture != null) { + mCancellationTaskFuture.cancel(/* may interrupt */ true); + } if (mAudioFlinger != null) { mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0); } @@ -481,12 +560,31 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onDetected"); } synchronized (mLock) { + // TODO: If the dsp trigger comes in after the timeout, we will log both events. + // Because we don't enforce the timeout yet. We should add some synchronizations + // within the runnable to prevent the race condition to log both events. + if (mCancellationKeyPhraseDetectionFuture != null) { + mCancellationKeyPhraseDetectionFuture.cancel(true); + } + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED); if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignoring #onDetected due to a process restart"); + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); return; } mValidatingDspTrigger = false; - enforcePermissionsForDataDelivery(); + try { + enforcePermissionsForDataDelivery(); + } catch (SecurityException e) { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); + throw e; + } externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) @@ -504,8 +602,17 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onRejected"); } synchronized (mLock) { + if (mCancellationKeyPhraseDetectionFuture != null) { + mCancellationKeyPhraseDetectionFuture.cancel(true); + } + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED); if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignoring #onRejected due to a process restart"); + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); return; } mValidatingDspTrigger = false; @@ -520,11 +627,20 @@ final class HotwordDetectionConnection { synchronized (mLock) { mValidatingDspTrigger = true; mRemoteHotwordDetectionService.run( - service -> service.detectFromDspSource( - recognitionEvent, - recognitionEvent.getCaptureFormat(), - VALIDATION_TIMEOUT_MILLIS, - internalCallback)); + service -> { + // TODO: avoid allocate every time + mCancellationKeyPhraseDetectionFuture = mScheduledExecutorService.schedule( + () -> HotwordMetricsLogger + .writeKeyphraseTriggerEvent(mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT), + VALIDATION_TIMEOUT_MILLIS, + TimeUnit.MILLISECONDS); + service.detectFromDspSource( + recognitionEvent, + recognitionEvent.getCaptureFormat(), + VALIDATION_TIMEOUT_MILLIS, + internalCallback); + }); } } @@ -625,10 +741,16 @@ final class HotwordDetectionConnection { } final boolean useHotwordDetectionService = mHotwordDetectionConnection != null; if (useHotwordDetectionService) { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER); mRecognitionEvent = recognitionEvent; mHotwordDetectionConnection.detectFromDspSource( recognitionEvent, mExternalCallback); } else { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER); mExternalCallback.onKeyphraseDetected(recognitionEvent, null); } } @@ -657,6 +779,7 @@ final class HotwordDetectionConnection { } public void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("RESTART_PERIOD_SECONDS="); pw.println(RESTART_PERIOD_SECONDS); pw.print(prefix); pw.print("mBound=" + mRemoteHotwordDetectionService.isBound()); pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger); @@ -793,6 +916,7 @@ final class HotwordDetectionConnection { private boolean mRespectServiceConnectionStatusChanged = true; private boolean mIsBound = false; + private boolean mIsLoggedFirstConnect = false; ServiceConnection(@NonNull Context context, @NonNull Intent intent, int bindingFlags, int userId, @@ -816,6 +940,12 @@ final class HotwordDetectionConnection { return; } mIsBound = connected; + if (connected && !mIsLoggedFirstConnect) { + mIsLoggedFirstConnect = true; + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED, + mVoiceInteractionServiceUid); + } } } @@ -846,13 +976,25 @@ final class HotwordDetectionConnection { protected boolean bindService( @NonNull android.content.ServiceConnection serviceConnection) { try { - return mContext.bindIsolatedService( + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE, + mVoiceInteractionServiceUid); + boolean bindResult = mContext.bindIsolatedService( mIntent, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags, "hotword_detector_" + mInstanceNumber, mExecutor, serviceConnection); + if (!bindResult) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL, + mVoiceInteractionServiceUid); + } + return bindResult; } catch (IllegalArgumentException e) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL, + mVoiceInteractionServiceUid); Slog.wtf(TAG, "Can't bind to the hotword detection service!", e); return false; } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java index de0b9606045e..940aed34b7fb 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java @@ -16,6 +16,24 @@ package com.android.server.voiceinteraction; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + +import android.service.voice.HotwordDetector; + import com.android.internal.util.FrameworkStatsLog; /** @@ -23,6 +41,13 @@ import com.android.internal.util.FrameworkStatsLog; */ public final class HotwordMetricsLogger { + private static final int METRICS_INIT_DETECTOR_SOFTWARE = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + private static final int METRICS_INIT_DETECTOR_DSP = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + private static final int METRICS_INIT_NORMAL_DETECTOR = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR; + private HotwordMetricsLogger() { // Class only contains static utility functions, and should not be instantiated } @@ -31,39 +56,99 @@ public final class HotwordMetricsLogger { * Logs information related to create hotword detector. */ public static void writeDetectorCreateEvent(int detectorType, boolean isCreated, int uid) { - FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED, detectorType, - isCreated, uid); + int metricsDetectorType = getCreateMetricsDetectorType(detectorType); + FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED, + metricsDetectorType, isCreated, uid); } /** * Logs information related to hotword detection service init result. */ public static void writeServiceInitResultEvent(int detectorType, int result) { + int metricsDetectorType = getInitMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED, - detectorType, result); + metricsDetectorType, result); } /** * Logs information related to hotword detection service restarting. */ public static void writeServiceRestartEvent(int detectorType, int reason) { + int metricsDetectorType = getRestartMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED, - detectorType, reason); + metricsDetectorType, reason); } /** * Logs information related to keyphrase trigger. */ public static void writeKeyphraseTriggerEvent(int detectorType, int result) { + int metricsDetectorType = getKeyphraseMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED, - detectorType, result); + metricsDetectorType, result); } /** * Logs information related to hotword detector events. */ public static void writeDetectorEvent(int detectorType, int event, int uid) { + int metricsDetectorType = getDetectorMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS, - detectorType, event, uid); + metricsDetectorType, event, uid); + } + + private static int getCreateMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } + + private static int getRestartMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } + + private static int getInitMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return METRICS_INIT_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return METRICS_INIT_DETECTOR_DSP; + default: + return METRICS_INIT_NORMAL_DETECTOR; + } + } + + private static int getKeyphraseMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } + + private static int getDetectorMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__NORMAL_DETECTOR; + } } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index fb4d73cf9d52..0519873810b5 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -462,24 +462,33 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne IHotwordRecognitionStatusCallback callback, int detectorType) { Slog.v(TAG, "updateStateLocked"); + int voiceInteractionServiceUid = mInfo.getServiceInfo().applicationInfo.uid; if (mHotwordDetectionComponentName == null) { Slog.w(TAG, "Hotword detection service name not found"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Hotword detection service name not found"); } ServiceInfo hotwordDetectionServiceInfo = getServiceInfoLocked( mHotwordDetectionComponentName, mUser); if (hotwordDetectionServiceInfo == null) { Slog.w(TAG, "Hotword detection service info not found"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Hotword detection service info not found"); } if (!isIsolatedProcessLocked(hotwordDetectionServiceInfo)) { Slog.w(TAG, "Hotword detection service not in isolated process"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Hotword detection service not in isolated process"); } if (!Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE.equals( hotwordDetectionServiceInfo.permission)) { Slog.w(TAG, "Hotword detection service does not require permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new SecurityException("Hotword detection service does not require permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); } @@ -488,17 +497,23 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne mInfo.getServiceInfo().packageName) == PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Voice interaction service should not hold permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new SecurityException("Voice interaction service should not hold permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); } if (sharedMemory != null && !sharedMemory.setProtect(OsConstants.PROT_READ)) { Slog.w(TAG, "Can't set sharedMemory to be read-only"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Can't set sharedMemory to be read-only"); } mDetectorType = detectorType; + logDetectorCreateEventIfNeeded(callback, detectorType, true, + voiceInteractionServiceUid); if (mHotwordDetectionConnection == null) { mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext, mInfo.getServiceInfo().applicationInfo.uid, voiceInteractorIdentity, @@ -509,6 +524,15 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne } } + private void logDetectorCreateEventIfNeeded(IHotwordRecognitionStatusCallback callback, + int detectorType, boolean isCreated, int voiceInteractionServiceUid) { + if (callback != null) { + HotwordMetricsLogger.writeDetectorCreateEvent(detectorType, true, + voiceInteractionServiceUid); + } + + } + public void shutdownHotwordDetectionServiceLocked() { if (DEBUG) { Slog.d(TAG, "shutdownHotwordDetectionServiceLocked"); diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index 3a3b3632dc9b..d2a4c3e7197c 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -1090,6 +1090,13 @@ public final class DataFailCause { */ public static final int NO_RETRY_FAILURE = 0x1000B; + /** + * Traffic descriptors in DataCallResponse is empty. + * + * @hide + */ + public static final int NO_TRAFFIC_DESCRIPTORS = 0x1000C; + private static final Map<Integer, String> sFailCauseMap; static { sFailCauseMap = new HashMap<>(); @@ -1524,6 +1531,7 @@ public final class DataFailCause { sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE"); sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED"); sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE"); + sFailCauseMap.put(NO_TRAFFIC_DESCRIPTORS, "NO_TRAFFIC_DESCRIPTORS"); } private DataFailCause() { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 1eb391d60e4d..3f430ab77df4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -8352,24 +8352,6 @@ public class TelephonyManager { } /** - * Get P-CSCF address from PCO after data connection is established or modified. - * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN - * @return array of P-CSCF address - * @hide - */ - public String[] getPcscfAddress(String apnType) { - try { - ITelephony telephony = getITelephony(); - if (telephony == null) - return new String[0]; - return telephony.getPcscfAddress(apnType, getOpPackageName(), getAttributionTag()); - } catch (RemoteException e) { - return new String[0]; - } - } - - - /** * Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot. * Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to * recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad @@ -16790,7 +16772,10 @@ public class TelephonyManager { * Callback to listen for when the set of packages with carrier privileges for a SIM changes. * * @hide + * @deprecated Use {@link CarrierPrivilegesCallback} instead. This API will be removed soon + * prior to API finalization. */ + @Deprecated @SystemApi public interface CarrierPrivilegesListener { /** @@ -16810,6 +16795,54 @@ public class TelephonyManager { } /** + * Callbacks to listen for when the set of packages with carrier privileges for a SIM changes. + * + * <p>Of note, when multiple callbacks are registered, they may be triggered one after another. + * The ordering of them is not guaranteed and thus should not be depend on. + * + * @hide + */ + @SystemApi + public interface CarrierPrivilegesCallback { + /** + * Called when the set of packages with carrier privileges has changed. + * + * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile + * switch and the same set of packages remains privileged after the switch. + * + * <p>At registration, the callback will receive the current set of privileged packages. + * + * @param privilegedPackageNames The updated set of package names that have carrier + * privileges + * @param privilegedUids The updated set of UIDs that have carrier privileges + */ + void onCarrierPrivilegesChanged( + @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids); + + /** + * Called when the {@link CarrierService} for the current user profile has changed. + * + * <p>This method does nothing by default. Clients that are interested in the carrier + * service change should override this method to get package name and UID info. + * + * <p>At registration, the callback will receive the current carrier service info. + * + * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile + * switch and the same carrier service remains after switch. + * + * @param carrierServicePackageName package name of the {@link CarrierService}. May be + * {@code null} when no carrier service is detected. + * @param carrierServiceUid UID of the {@link CarrierService}. May be + * {@link android.os.Process#INVALID_UID} if no carrier + * service is detected. + */ + default void onCarrierServiceChanged( + @Nullable String carrierServicePackageName, int carrierServiceUid) { + // do nothing by default + } + } + + /** * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to * receive callbacks when the set of packages with carrier privileges changes. The callback will * immediately be called with the latest state. @@ -16818,7 +16851,10 @@ public class TelephonyManager { * @param executor The executor where {@code listener} will be invoked * @param listener The callback to register * @hide + * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be + * removed prior to API finalization. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener( @@ -16842,7 +16878,10 @@ public class TelephonyManager { * Unregisters an existing {@link CarrierPrivilegesListener}. * * @hide + * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be + * removed prior to API finalization. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) { @@ -16890,4 +16929,53 @@ public class TelephonyManager { ex.rethrowAsRuntimeException(); } } + + /** + * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to + * receive callbacks when the set of packages with carrier privileges changes. The callback will + * immediately be called with the latest state. + * + * @param logicalSlotIndex The SIM slot to listen on + * @param executor The executor where {@code callback} will be invoked + * @param callback The callback to register + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void registerCarrierPrivilegesCallback( + int logicalSlotIndex, + @NonNull @CallbackExecutor Executor executor, + @NonNull CarrierPrivilegesCallback callback) { + if (mContext == null) { + throw new IllegalStateException("Telephony service is null"); + } else if (executor == null || callback == null) { + throw new IllegalArgumentException( + "CarrierPrivilegesCallback and executor must be non-null"); + } + mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); + if (mTelephonyRegistryMgr == null) { + throw new IllegalStateException("Telephony registry service is null"); + } + mTelephonyRegistryMgr.addCarrierPrivilegesCallback(logicalSlotIndex, executor, callback); + } + + /** + * Unregisters an existing {@link CarrierPrivilegesCallback}. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void unregisterCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) { + if (mContext == null) { + throw new IllegalStateException("Telephony service is null"); + } else if (callback == null) { + throw new IllegalArgumentException("CarrierPrivilegesCallback must be non-null"); + } + mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); + if (mTelephonyRegistryMgr == null) { + throw new IllegalStateException("Telephony registry service is null"); + } + mTelephonyRegistryMgr.removeCarrierPrivilegesCallback(callback); + } } diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index fc94ebf2cc37..532679cb6c43 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -1103,8 +1103,10 @@ public class ApnSetting implements Parcelable { sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType)); sb.append(", ").append(mMvnoMatchData); sb.append(", ").append(mPermanentFailed); - sb.append(", ").append(mNetworkTypeBitmask); - sb.append(", ").append(mLingeringNetworkTypeBitmask); + sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString( + mNetworkTypeBitmask)); + sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString( + mLingeringNetworkTypeBitmask)); sb.append(", ").append(mApnSetId); sb.append(", ").append(mCarrierId); sb.append(", ").append(mSkip464Xlat); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index dc96b3585864..a5e2c1f83939 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -978,14 +978,6 @@ interface ITelephony { boolean isManualNetworkSelectionAllowed(int subId); /** - * Get P-CSCF address from PCO after data connection is established or modified. - * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN - * @param callingPackage The package making the call. - * @param callingFeatureId The feature in the package. - */ - String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId); - - /** * Set IMS registration state */ void setImsRegistrationState(boolean registered); diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt index b0e53e9f85bf..c3a4769bc573 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt @@ -74,7 +74,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) * Checks that the nav bar layer starts invisible, becomes visible during unlocking animation * and remains visible at the end */ - @Postsubmit + @Presubmit @Test fun navBarLayerVisibilityChanges() { testSpec.assertLayers { 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() { diff --git a/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java index 9658d6f6a698..164f61c4c630 100644 --- a/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java +++ b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java @@ -37,7 +37,7 @@ public class BaseComponentAliasTest { protected static final Context sContext = InstrumentationRegistry.getTargetContext(); protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER); + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS); @Before public void enableComponentAliasWithCompatFlag() throws Exception { Assume.assumeTrue(Build.isDebuggable()); diff --git a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasEnableWithDeviceConfigTest.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasEnableWithDeviceConfigTest.java index 52c6d5b8ae12..ee20379d971a 100644 --- a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasEnableWithDeviceConfigTest.java +++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasEnableWithDeviceConfigTest.java @@ -28,7 +28,7 @@ import org.junit.Test; public class ComponentAliasEnableWithDeviceConfigTest { protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER); + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS); @AfterClass public static void restoreDeviceConfig() throws Exception { diff --git a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasNotSupportedOnUserBuildTest.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasNotSupportedOnUserBuildTest.java index 7935476d6156..0899886fe951 100644 --- a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasNotSupportedOnUserBuildTest.java +++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasNotSupportedOnUserBuildTest.java @@ -32,7 +32,7 @@ import org.junit.Test; */ public class ComponentAliasNotSupportedOnUserBuildTest { protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER); + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS); @AfterClass public static void restoreDeviceConfig() throws Exception { diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java index 7b1f7a599519..b67395735426 100644 --- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java @@ -60,7 +60,7 @@ import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; -import android.telephony.TelephonyManager.CarrierPrivilegesListener; +import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.util.ArrayMap; import android.util.ArraySet; @@ -187,11 +187,11 @@ public class TelephonySubscriptionTrackerTest { return captor.getValue(); } - private List<CarrierPrivilegesListener> getCarrierPrivilegesListeners() { - final ArgumentCaptor<CarrierPrivilegesListener> captor = - ArgumentCaptor.forClass(CarrierPrivilegesListener.class); + private List<CarrierPrivilegesCallback> getCarrierPrivilegesCallbacks() { + final ArgumentCaptor<CarrierPrivilegesCallback> captor = + ArgumentCaptor.forClass(CarrierPrivilegesCallback.class); verify(mTelephonyManager, atLeastOnce()) - .addCarrierPrivilegesListener(anyInt(), any(), captor.capture()); + .registerCarrierPrivilegesCallback(anyInt(), any(), captor.capture()); return captor.getAllValues(); } @@ -270,12 +270,12 @@ public class TelephonySubscriptionTrackerTest { assertNotNull(getOnSubscriptionsChangedListener()); verify(mTelephonyManager, times(2)) - .addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any()); + .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any()); verify(mTelephonyManager) - .addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any()); + .registerCarrierPrivilegesCallback(eq(0), any(HandlerExecutor.class), any()); verify(mTelephonyManager) - .addCarrierPrivilegesListener(eq(1), any(HandlerExecutor.class), any()); - assertEquals(2, getCarrierPrivilegesListeners().size()); + .registerCarrierPrivilegesCallback(eq(1), any(HandlerExecutor.class), any()); + assertEquals(2, getCarrierPrivilegesCallbacks().size()); } @Test @@ -287,10 +287,10 @@ public class TelephonySubscriptionTrackerTest { final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener)); - for (CarrierPrivilegesListener carrierPrivilegesListener : - getCarrierPrivilegesListeners()) { + for (CarrierPrivilegesCallback carrierPrivilegesCallback : + getCarrierPrivilegesCallbacks()) { verify(mTelephonyManager) - .removeCarrierPrivilegesListener(eq(carrierPrivilegesListener)); + .unregisterCarrierPrivilegesCallback(eq(carrierPrivilegesCallback)); } } @@ -303,15 +303,15 @@ public class TelephonySubscriptionTrackerTest { mTelephonySubscriptionTracker.setReadySubIdsBySlotId(readySubIdsBySlotId); doReturn(1).when(mTelephonyManager).getActiveModemCount(); - List<CarrierPrivilegesListener> carrierPrivilegesListeners = - getCarrierPrivilegesListeners(); + List<CarrierPrivilegesCallback> carrierPrivilegesCallbacks = + getCarrierPrivilegesCallbacks(); mTelephonySubscriptionTracker.onReceive(mContext, buildTestMultiSimConfigBroadcastIntent()); mTestLooper.dispatchAll(); - for (CarrierPrivilegesListener carrierPrivilegesListener : carrierPrivilegesListeners) { + for (CarrierPrivilegesCallback carrierPrivilegesCallback : carrierPrivilegesCallbacks) { verify(mTelephonyManager) - .removeCarrierPrivilegesListener(eq(carrierPrivilegesListener)); + .unregisterCarrierPrivilegesCallback(eq(carrierPrivilegesCallback)); } // Expect cache cleared for inactive slots. @@ -323,9 +323,9 @@ public class TelephonySubscriptionTrackerTest { // Expect a new CarrierPrivilegesListener to have been registered for slot 0, and none other // (2 previously registered during startup, for slots 0 & 1) verify(mTelephonyManager, times(3)) - .addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any()); + .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any()); verify(mTelephonyManager, times(2)) - .addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any()); + .registerCarrierPrivilegesCallback(eq(0), any(HandlerExecutor.class), any()); // Verify that this triggers a re-evaluation verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); @@ -391,8 +391,8 @@ public class TelephonySubscriptionTrackerTest { public void testOnCarrierPrivilegesChanged() throws Exception { setupReadySubIds(); - final CarrierPrivilegesListener listener = getCarrierPrivilegesListeners().get(0); - listener.onCarrierPrivilegesChanged(Collections.emptyList(), new int[] {}); + final CarrierPrivilegesCallback callback = getCarrierPrivilegesCallbacks().get(0); + callback.onCarrierPrivilegesChanged(Collections.emptySet(), Collections.emptySet()); mTestLooper.dispatchAll(); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp index 0423b7abd685..ff24d160b917 100644 --- a/tools/validatekeymaps/Android.bp +++ b/tools/validatekeymaps/Android.bp @@ -32,7 +32,7 @@ cc_binary_host { "libui-types", ], target: { - linux_glibc: { + host_linux: { static_libs: [ // libbinder is only available for linux "libbinder", diff --git a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java index 8630ec4b062d..d85a5bdc3e66 100644 --- a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java +++ b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java @@ -967,16 +967,16 @@ public class WifiNl80211Manager { * * @param ifaceName Name of the interface. */ - public int getMaxNumScanSsids(@NonNull String ifaceName) { + public int getMaxSsidsPerScan(@NonNull String ifaceName) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); return 0; } try { - return scannerImpl.getMaxNumScanSsids(); + return scannerImpl.getMaxSsidsPerScan(); } catch (RemoteException e1) { - Log.e(TAG, "Failed to getMaxNumScanSsids"); + Log.e(TAG, "Failed to getMaxSsidsPerScan"); } return 0; } |