diff options
162 files changed, 4340 insertions, 2078 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java index 5b1405628b49..cb1e6d9dc0a4 100644 --- a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java +++ b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java @@ -32,7 +32,7 @@ import android.os.ServiceManager; public class DeviceIdleFrameworkInitializer { private static IDeviceIdleController sIDeviceIdleController; - static { + public static void initialize() { SystemServiceRegistry.registerCachedService( Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class, (context, b) -> new DeviceIdleManager( diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java index c90b8728bf4a..cc6ca3dd6cbf 100644 --- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java +++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java @@ -28,7 +28,7 @@ import android.os.BatteryStats; * @hide */ public class JobSchedulerFrameworkInitializer { - static { + public static void initialize() { SystemServiceRegistry.registerStaticService( Context.JOB_SCHEDULER_SERVICE, JobScheduler.class, (b) -> new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b))); diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index a1734d8d25d5..eb22d0907525 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -899,7 +899,8 @@ public class JobSchedulerService extends com.android.server.SystemService } final private IUidObserver mUidObserver = new IUidObserver.Stub() { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { + @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, + int capability) { mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget(); } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index cda524418664..3aef5d1d59e3 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -466,7 +466,7 @@ public final class QuotaController extends StateController { private final IUidObserver mUidObserver = new IUidObserver.Stub() { @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) { + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { mHandler.obtainMessage(MSG_UID_PROCESS_STATE_CHANGED, uid, procState).sendToTarget(); } diff --git a/api/current.txt b/api/current.txt index 6278179bc120..276fddc437f8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2827,7 +2827,7 @@ package android.accessibilityservice { method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method @NonNull public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController(); method @NonNull public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController(int); - method @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) @NonNull public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController(); + method @NonNull @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController(); method @NonNull public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController(); method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow(); method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); @@ -3541,11 +3541,11 @@ package android.animation { package android.annotation { - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface SuppressLint { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressLint { method public abstract String[] value(); } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface TargetApi { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) public @interface TargetApi { method public abstract int value(); } @@ -3758,7 +3758,7 @@ package android.app { method public void onContentChanged(); method public boolean onContextItemSelected(@NonNull android.view.MenuItem); method public void onContextMenuClosed(@NonNull android.view.Menu); - method @MainThread @CallSuper protected void onCreate(@Nullable android.os.Bundle); + method @CallSuper @MainThread protected void onCreate(@Nullable android.os.Bundle); method public void onCreate(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle); method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo); method @Nullable public CharSequence onCreateDescription(); @@ -3901,8 +3901,8 @@ package android.app { method @Deprecated public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle); method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int); method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle); - method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int); - method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int, @Nullable android.os.Bundle); + method public boolean startActivityIfNeeded(@NonNull @RequiresPermission android.content.Intent, int); + method public boolean startActivityIfNeeded(@NonNull @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle); method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method @Deprecated public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; @@ -3910,8 +3910,8 @@ package android.app { method public void startLocalVoiceInteraction(android.os.Bundle); method public void startLockTask(); method @Deprecated public void startManagingCursor(android.database.Cursor); - method public boolean startNextMatchingActivity(@RequiresPermission @NonNull android.content.Intent); - method public boolean startNextMatchingActivity(@RequiresPermission @NonNull android.content.Intent, @Nullable android.os.Bundle); + method public boolean startNextMatchingActivity(@NonNull @RequiresPermission android.content.Intent); + method public boolean startNextMatchingActivity(@NonNull @RequiresPermission android.content.Intent, @Nullable android.os.Bundle); method public void startPostponedEnterTransition(); method public void startSearch(@Nullable String, boolean, @Nullable android.os.Bundle, boolean); method public void stopLocalVoiceInteraction(); @@ -6714,7 +6714,7 @@ package android.app.admin { method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName); method @Nullable public java.util.Set<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName); method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName); - method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String); + method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String); method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName); method public boolean getAutoTimeRequired(); method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName); @@ -7640,7 +7640,7 @@ package android.app.slice { method public int checkSlicePermission(@NonNull android.net.Uri, int, int); method @NonNull public java.util.List<android.net.Uri> getPinnedSlices(); method @NonNull public java.util.Set<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri); - method @WorkerThread @NonNull public java.util.Collection<android.net.Uri> getSliceDescendants(@NonNull android.net.Uri); + method @NonNull @WorkerThread public java.util.Collection<android.net.Uri> getSliceDescendants(@NonNull android.net.Uri); method public void grantSlicePermission(@NonNull String, @NonNull android.net.Uri); method @Nullable public android.net.Uri mapIntentToUri(@NonNull android.content.Intent); method public void pinSlice(@NonNull android.net.Uri, @NonNull java.util.Set<android.app.slice.SliceSpec>); @@ -7796,10 +7796,10 @@ package android.app.usage { public class StorageStatsManager { method @WorkerThread public long getFreeBytes(@NonNull java.util.UUID) throws java.io.IOException; method @WorkerThread public long getTotalBytes(@NonNull java.util.UUID) throws java.io.IOException; - method @WorkerThread @NonNull public android.app.usage.ExternalStorageStats queryExternalStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; - method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; - method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForUid(@NonNull java.util.UUID, int) throws java.io.IOException; - method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; + method @NonNull @WorkerThread public android.app.usage.ExternalStorageStats queryExternalStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; + method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForUid(@NonNull java.util.UUID, int) throws java.io.IOException; + method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; } public final class UsageEvents implements android.os.Parcelable { @@ -8059,9 +8059,9 @@ package android.bluetooth { method public boolean isMultipleAdvertisementSupported(); method public boolean isOffloadedFilteringSupported(); method public boolean isOffloadedScanBatchingSupported(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery(); @@ -8429,9 +8429,9 @@ package android.bluetooth { method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int); method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; method public int describeContents(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp(); @@ -9616,14 +9616,14 @@ package android.content { method public static void addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long); method public static Object addStatusChangeListener(int, android.content.SyncStatusObserver); method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull String, @NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException; - method public final int bulkInsert(@RequiresPermission.Write @NonNull android.net.Uri, @NonNull android.content.ContentValues[]); + method public final int bulkInsert(@NonNull @RequiresPermission.Write android.net.Uri, @NonNull android.content.ContentValues[]); method @Nullable public final android.os.Bundle call(@NonNull android.net.Uri, @NonNull String, @Nullable String, @Nullable android.os.Bundle); method @Nullable public final android.os.Bundle call(@NonNull String, @NonNull String, @Nullable String, @Nullable android.os.Bundle); method @Deprecated public void cancelSync(android.net.Uri); method public static void cancelSync(android.accounts.Account, String); method public static void cancelSync(android.content.SyncRequest); method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri); - method public final int delete(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable String, @Nullable String[]); + method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable String, @Nullable String[]); method @Deprecated public static android.content.SyncInfo getCurrentSync(); method public static java.util.List<android.content.SyncInfo> getCurrentSyncs(); method public static int getIsSyncable(android.accounts.Account, String); @@ -9636,7 +9636,7 @@ package android.content { method public static boolean getSyncAutomatically(android.accounts.Account, String); method @Nullable public final String getType(@NonNull android.net.Uri); method @NonNull public final android.content.ContentResolver.MimeTypeInfo getTypeInfo(@NonNull String); - method @Nullable public final android.net.Uri insert(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues); + method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues); method public static boolean isSyncActive(android.accounts.Account, String); method public static boolean isSyncPending(android.accounts.Account, String); method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException; @@ -9655,9 +9655,9 @@ package android.content { method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException; method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle) throws java.io.FileNotFoundException; method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException; - method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String); - method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal); - method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal); + method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String); + method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal); + method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal); method public final boolean refresh(@NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal); method public final void registerContentObserver(@NonNull android.net.Uri, boolean, @NonNull android.database.ContentObserver); method public void releasePersistableUriPermission(@NonNull android.net.Uri, int); @@ -9672,7 +9672,7 @@ package android.content { method public void takePersistableUriPermission(@NonNull android.net.Uri, int); method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri); method public final void unregisterContentObserver(@NonNull android.database.ContentObserver); - method public final int update(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]); + method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]); method public static void validateSyncExtrasBundle(android.os.Bundle); method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider); method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient); @@ -9770,9 +9770,9 @@ package android.content { public abstract class Context { ctor public Context(); - method public boolean bindIsolatedService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); + method public boolean bindIsolatedService(@NonNull @RequiresPermission android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); method public abstract boolean bindService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int); - method public boolean bindService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); + method public boolean bindService(@NonNull @RequiresPermission android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") public abstract int checkCallingOrSelfPermission(@NonNull String); method @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int); method @CheckResult(suggest="#enforceCallingPermission(String,String)") public abstract int checkCallingPermission(@NonNull String); @@ -9871,7 +9871,7 @@ package android.content { method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String); method public abstract void sendOrderedBroadcast(@RequiresPermission android.content.Intent, @Nullable String); - method public abstract void sendOrderedBroadcast(@RequiresPermission @NonNull android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); + method public abstract void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendOrderedBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyBroadcast(@RequiresPermission android.content.Intent); method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void sendStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); @@ -11725,7 +11725,7 @@ package android.content.pm { method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle, @Nullable android.graphics.Rect, int); method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedIcon(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle); method @NonNull public abstract CharSequence getUserBadgedLabel(@NonNull CharSequence, @NonNull android.os.UserHandle); - method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int); + method @NonNull @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int); method @Nullable public abstract android.content.res.XmlResourceParser getXml(@NonNull String, @XmlRes int, @Nullable android.content.pm.ApplicationInfo); method public boolean hasSigningCertificate(@NonNull String, @NonNull byte[], int); method public boolean hasSigningCertificate(int, @NonNull byte[], int); @@ -12419,7 +12419,7 @@ package android.content.res { method public int addLoader(@NonNull android.content.res.loader.ResourceLoader, @NonNull android.content.res.loader.ResourcesProvider); method public final void finishPreloading(); method public final void flushLayoutCache(); - method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimatorRes @AnimRes int) throws android.content.res.Resources.NotFoundException; + method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimRes @AnimatorRes int) throws android.content.res.Resources.NotFoundException; method public final android.content.res.AssetManager getAssets(); method @AnyRes public static int getAttributeSetSourceResId(@Nullable android.util.AttributeSet); method public boolean getBoolean(@BoolRes int) throws android.content.res.Resources.NotFoundException; @@ -13725,10 +13725,10 @@ package android.graphics { method public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean); method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); - method public static android.graphics.Bitmap createBitmap(@NonNull @ColorInt int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @NonNull @ColorInt int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@NonNull @ColorInt int[], int, int, android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @NonNull @ColorInt int[], int, int, @NonNull android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, @NonNull android.graphics.Bitmap.Config); method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture); method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture, int, int, @NonNull android.graphics.Bitmap.Config); method public static android.graphics.Bitmap createScaledBitmap(@NonNull android.graphics.Bitmap, int, int, boolean); @@ -13961,8 +13961,8 @@ package android.graphics { method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, float, float, @NonNull android.graphics.RectF, float, float, @NonNull android.graphics.Paint); method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.Paint); method public void drawLine(float, float, float, float, @NonNull android.graphics.Paint); - method public void drawLines(@Size(multiple=4) @NonNull float[], int, int, @NonNull android.graphics.Paint); - method public void drawLines(@Size(multiple=4) @NonNull float[], @NonNull android.graphics.Paint); + method public void drawLines(@NonNull @Size(multiple=4) float[], int, int, @NonNull android.graphics.Paint); + method public void drawLines(@NonNull @Size(multiple=4) float[], @NonNull android.graphics.Paint); method public void drawOval(@NonNull android.graphics.RectF, @NonNull android.graphics.Paint); method public void drawOval(float, float, float, float, @NonNull android.graphics.Paint); method public void drawPaint(@NonNull android.graphics.Paint); @@ -13972,7 +13972,7 @@ package android.graphics { method public void drawPicture(@NonNull android.graphics.Picture, @NonNull android.graphics.Rect); method public void drawPoint(float, float, @NonNull android.graphics.Paint); method public void drawPoints(@Size(multiple=2) float[], int, int, @NonNull android.graphics.Paint); - method public void drawPoints(@Size(multiple=2) @NonNull float[], @NonNull android.graphics.Paint); + method public void drawPoints(@NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint); method @Deprecated public void drawPosText(@NonNull char[], int, int, @NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint); method @Deprecated public void drawPosText(@NonNull String, @NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint); method public void drawRGB(int, int, int); @@ -14333,10 +14333,10 @@ package android.graphics { method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.nio.ByteBuffer); method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.io.File); method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.util.concurrent.Callable<android.content.res.AssetFileDescriptor>); - method @WorkerThread @NonNull public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; - method @WorkerThread @NonNull public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; - method @WorkerThread @NonNull public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; - method @WorkerThread @NonNull public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; method public int getAllocator(); method @Nullable public android.graphics.Rect getCrop(); method public int getMemorySizePolicy(); @@ -14355,7 +14355,7 @@ package android.graphics { method public void setPostProcessor(@Nullable android.graphics.PostProcessor); method public void setTargetColorSpace(android.graphics.ColorSpace); method public void setTargetSampleSize(@IntRange(from=1) int); - method public void setTargetSize(@Px @IntRange(from=1) int, @Px @IntRange(from=1) int); + method public void setTargetSize(@IntRange(from=1) @Px int, @IntRange(from=1) @Px int); method public void setUnpremultipliedRequired(boolean); field public static final int ALLOCATOR_DEFAULT = 0; // 0x0 field public static final int ALLOCATOR_HARDWARE = 3; // 0x3 @@ -14462,8 +14462,8 @@ package android.graphics { } public class LinearGradient extends android.graphics.Shader { - ctor public LinearGradient(float, float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); - ctor public LinearGradient(float, float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public LinearGradient(float, float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public LinearGradient(float, float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode); } @@ -15006,8 +15006,8 @@ package android.graphics { } public class RadialGradient extends android.graphics.Shader { - ctor public RadialGradient(float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); - ctor public RadialGradient(float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode); } @@ -15265,8 +15265,8 @@ package android.graphics { } public class SweepGradient extends android.graphics.Shader { - ctor public SweepGradient(float, float, @NonNull @ColorInt int[], @Nullable float[]); - ctor public SweepGradient(float, float, @NonNull @ColorLong long[], @Nullable float[]); + ctor public SweepGradient(float, float, @ColorInt @NonNull int[], @Nullable float[]); + ctor public SweepGradient(float, float, @ColorLong @NonNull long[], @Nullable float[]); ctor public SweepGradient(float, float, @ColorInt int, @ColorInt int); ctor public SweepGradient(float, float, @ColorLong long, @ColorLong long); } @@ -15659,8 +15659,8 @@ package android.graphics.drawable { method public void setColor(@ColorInt int); method public void setColor(@Nullable android.content.res.ColorStateList); method public void setColorFilter(@Nullable android.graphics.ColorFilter); - method public void setColors(@Nullable @ColorInt int[]); - method public void setColors(@Nullable @ColorInt int[], @Nullable float[]); + method public void setColors(@ColorInt @Nullable int[]); + method public void setColors(@ColorInt @Nullable int[], @Nullable float[]); method public void setCornerRadii(@Nullable float[]); method public void setCornerRadius(float); method public void setDither(boolean); @@ -16108,14 +16108,14 @@ package android.graphics.text { public static class LineBreaker.ParagraphConstraints { ctor public LineBreaker.ParagraphConstraints(); - method @Px @FloatRange(from=0) public float getDefaultTabStop(); - method @Px @FloatRange(from=0.0f) public float getFirstWidth(); - method @Px @IntRange(from=0) public int getFirstWidthLineCount(); + method @FloatRange(from=0) @Px public float getDefaultTabStop(); + method @FloatRange(from=0.0f) @Px public float getFirstWidth(); + method @IntRange(from=0) @Px public int getFirstWidthLineCount(); method @Nullable public float[] getTabStops(); - method @Px @FloatRange(from=0.0f) public float getWidth(); - method public void setIndent(@Px @FloatRange(from=0.0f) float, @Px @IntRange(from=0) int); - method public void setTabStops(@Nullable float[], @Px @FloatRange(from=0) float); - method public void setWidth(@Px @FloatRange(from=0.0f) float); + method @FloatRange(from=0.0f) @Px public float getWidth(); + method public void setIndent(@FloatRange(from=0.0f) @Px float, @IntRange(from=0) @Px int); + method public void setTabStops(@Nullable float[], @FloatRange(from=0) @Px float); + method public void setWidth(@FloatRange(from=0.0f) @Px float); } public static class LineBreaker.Result { @@ -16138,7 +16138,7 @@ package android.graphics.text { public static final class MeasuredText.Builder { ctor public MeasuredText.Builder(@NonNull char[]); ctor public MeasuredText.Builder(@NonNull android.graphics.text.MeasuredText); - method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @Px @FloatRange(from=0) float); + method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float); method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean); method @NonNull public android.graphics.text.MeasuredText build(); method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean); @@ -23157,7 +23157,7 @@ package android.location { method @Nullable public String getGnssHardwareModelName(); method public int getGnssYearOfHardware(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus); - method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) @Nullable public android.location.Location getLastKnownLocation(@NonNull String); + method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String); method @Nullable public android.location.LocationProvider getProvider(@NonNull String); method @NonNull public java.util.List<java.lang.String> getProviders(boolean); method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean); @@ -28628,17 +28628,17 @@ package android.net { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public boolean bindProcessToNetwork(@Nullable android.net.Network); method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.Network getActiveNetwork(); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo(); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @NonNull public android.net.Network[] getAllNetworks(); + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks(); method @Deprecated public boolean getBackgroundDataSetting(); method @Nullable public android.net.Network getBoundNetworkForProcess(); method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress); method @Nullable public android.net.ProxyInfo getDefaultProxy(); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network); method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference(); @@ -30010,7 +30010,7 @@ package android.net.wifi { method public android.net.wifi.WifiInfo getConnectionInfo(); method public android.net.DhcpInfo getDhcpInfo(); method public int getMaxNumberOfNetworkSuggestionsPerApp(); - method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) @NonNull public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions(); + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions(); method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations(); method public java.util.List<android.net.wifi.ScanResult> getScanResults(); method public int getWifiState(); @@ -30961,10 +30961,10 @@ package android.nfc.cardemulation { method public boolean isDefaultServiceForCategory(android.content.ComponentName, String); method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>); method public boolean removeAidsForService(android.content.ComponentName, String); - method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); + method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); method public boolean supportsAidPrefixRegistration(); - method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean unsetOffHostForService(@NonNull android.content.ComponentName); + method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName); method public boolean unsetPreferredService(android.app.Activity); field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; field public static final String CATEGORY_OTHER = "other"; @@ -34620,7 +34620,7 @@ package android.os { method public void addData(String, byte[], int); method public void addFile(String, java.io.File, int) throws java.io.IOException; method public void addText(String, String); - method @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.DropBoxManager.Entry getNextEntry(String, long); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.DropBoxManager.Entry getNextEntry(String, long); method public boolean isTagEnabled(String); field public static final String ACTION_DROPBOX_ENTRY_ADDED = "android.intent.action.DROPBOX_ENTRY_ADDED"; field public static final String EXTRA_DROPPED_COUNT = "android.os.extra.DROPPED_COUNT"; @@ -35506,7 +35506,7 @@ package android.os { method public String getUserName(); method public java.util.List<android.os.UserHandle> getUserProfiles(); method public android.os.Bundle getUserRestrictions(); - method public android.os.Bundle getUserRestrictions(android.os.UserHandle); + method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle); method public boolean hasUserRestriction(String); method public boolean isDemoUser(); method public boolean isQuietModeEnabled(android.os.UserHandle); @@ -44037,7 +44037,7 @@ package android.telecom { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts(); method public android.telecom.PhoneAccountHandle getSimCallManager(); method @Nullable public String getSystemDialerPackage(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle); @@ -44966,6 +44966,7 @@ package android.telephony { method public static int getDefaultSmsSubscriptionId(); method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback); + method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress(); method public int getSubscriptionId(); method public void injectSmsPdu(byte[], String, android.app.PendingIntent); method public void sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); @@ -44973,6 +44974,7 @@ package android.telephony { method public void sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>); method public void sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.SEND_SMS}) public void sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSmscAddress(@NonNull String); field public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; field public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; field public static final String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; @@ -45273,9 +45275,9 @@ package android.telephony { method public int getDataState(); method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(); method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(int); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public String getDeviceSoftwareVersion(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String[] getForbiddenPlmns(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getGroupIdLevel1(); method public String getIccAuthentication(int, int, String); @@ -45309,11 +45311,12 @@ package android.telephony { method @Nullable public CharSequence getSimSpecificCarrierIdName(); method public int getSimState(); method public int getSimState(int); + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubIdForPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId(); method public int getSupportedModemCount(); method @Nullable public String getTypeAllocationCode(); method @Nullable public String getTypeAllocationCode(int); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo(); + method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(); @@ -47247,7 +47250,7 @@ package android.text.style { } public static class LineHeightSpan.Standard implements android.text.style.LineHeightSpan android.text.ParcelableSpan { - ctor public LineHeightSpan.Standard(@Px @IntRange(from=1) int); + ctor public LineHeightSpan.Standard(@IntRange(from=1) @Px int); ctor public LineHeightSpan.Standard(@NonNull android.os.Parcel); method public void chooseHeight(@NonNull CharSequence, int, int, int, int, @NonNull android.graphics.Paint.FontMetricsInt); method public int describeContents(); @@ -51393,11 +51396,11 @@ package android.view { field @Deprecated public static final boolean TRACE_RECYCLER = false; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.CapturedViewProperty { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) public static @interface ViewDebug.CapturedViewProperty { method public abstract boolean retrieveReturn() default false; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.ExportedProperty { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) public static @interface ViewDebug.ExportedProperty { method public abstract String category() default ""; method public abstract boolean deepExport() default false; method public abstract android.view.ViewDebug.FlagToString[] flagMapping() default {}; @@ -51409,7 +51412,7 @@ package android.view { method public abstract boolean resolveId() default false; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.FlagToString { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface ViewDebug.FlagToString { method public abstract int equals(); method public abstract int mask(); method public abstract String name(); @@ -51427,7 +51430,7 @@ package android.view { enum_constant @Deprecated public static final android.view.ViewDebug.HierarchyTraceType REQUEST_LAYOUT; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.IntToString { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface ViewDebug.IntToString { method public abstract int from(); method public abstract String to(); } @@ -53985,18 +53988,18 @@ package android.view.textclassifier { } public interface TextClassifier { - method @WorkerThread @NonNull public default android.view.textclassifier.TextClassification classifyText(@NonNull android.view.textclassifier.TextClassification.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextClassification classifyText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); + method @NonNull @WorkerThread public default android.view.textclassifier.TextClassification classifyText(@NonNull android.view.textclassifier.TextClassification.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextClassification classifyText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); method public default void destroy(); - method @WorkerThread @NonNull public default android.view.textclassifier.TextLanguage detectLanguage(@NonNull android.view.textclassifier.TextLanguage.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextLinks generateLinks(@NonNull android.view.textclassifier.TextLinks.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextLanguage detectLanguage(@NonNull android.view.textclassifier.TextLanguage.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextLinks generateLinks(@NonNull android.view.textclassifier.TextLinks.Request); method @WorkerThread public default int getMaxGenerateLinksTextLength(); method public default boolean isDestroyed(); method public default void onSelectionEvent(@NonNull android.view.textclassifier.SelectionEvent); method public default void onTextClassifierEvent(@NonNull android.view.textclassifier.TextClassifierEvent); - method @WorkerThread @NonNull public default android.view.textclassifier.ConversationActions suggestConversationActions(@NonNull android.view.textclassifier.ConversationActions.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextSelection suggestSelection(@NonNull android.view.textclassifier.TextSelection.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextSelection suggestSelection(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); + method @NonNull @WorkerThread public default android.view.textclassifier.ConversationActions suggestConversationActions(@NonNull android.view.textclassifier.ConversationActions.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextSelection suggestSelection(@NonNull android.view.textclassifier.TextSelection.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextSelection suggestSelection(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); field public static final String EXTRA_FROM_TEXT_CLASSIFIER = "android.view.textclassifier.extra.FROM_TEXT_CLASSIFIER"; field public static final String HINT_TEXT_IS_EDITABLE = "android.text_is_editable"; field public static final String HINT_TEXT_IS_NOT_EDITABLE = "android.text_is_not_editable"; @@ -56460,12 +56463,12 @@ package android.widget { ctor public Magnifier.Builder(@NonNull android.view.View); method @NonNull public android.widget.Magnifier build(); method @NonNull public android.widget.Magnifier.Builder setClippingEnabled(boolean); - method @NonNull public android.widget.Magnifier.Builder setCornerRadius(@Px @FloatRange(from=0) float); + method @NonNull public android.widget.Magnifier.Builder setCornerRadius(@FloatRange(from=0) @Px float); method @NonNull public android.widget.Magnifier.Builder setDefaultSourceToMagnifierOffset(@Px int, @Px int); - method @NonNull public android.widget.Magnifier.Builder setElevation(@Px @FloatRange(from=0) float); + method @NonNull public android.widget.Magnifier.Builder setElevation(@FloatRange(from=0) @Px float); method @NonNull public android.widget.Magnifier.Builder setInitialZoom(@FloatRange(from=0.0f) float); method @NonNull public android.widget.Magnifier.Builder setOverlay(@Nullable android.graphics.drawable.Drawable); - method @NonNull public android.widget.Magnifier.Builder setSize(@Px @IntRange(from=0) int, @Px @IntRange(from=0) int); + method @NonNull public android.widget.Magnifier.Builder setSize(@IntRange(from=0) @Px int, @IntRange(from=0) @Px int); method @NonNull public android.widget.Magnifier.Builder setSourceBounds(int, int, int, int); } @@ -56959,7 +56962,7 @@ package android.widget { method @NonNull public static android.widget.RemoteViews.RemoteResponse fromPendingIntent(@NonNull android.app.PendingIntent); } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface RemoteViews.RemoteView { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface RemoteViews.RemoteView { } public abstract class RemoteViewsService extends android.app.Service { @@ -57636,7 +57639,7 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFallbackLineSpacing(boolean); method public void setFilters(android.text.InputFilter[]); - method public void setFirstBaselineToTopHeight(@Px @IntRange(from=0) int); + method public void setFirstBaselineToTopHeight(@IntRange(from=0) @Px int); method public void setFontFeatureSettings(@Nullable String); method public boolean setFontVariationSettings(@Nullable String); method protected boolean setFrame(int, int, int, int); @@ -57658,9 +57661,9 @@ package android.widget { method public void setInputType(int); method public void setJustificationMode(int); method public void setKeyListener(android.text.method.KeyListener); - method public void setLastBaselineToBottomHeight(@Px @IntRange(from=0) int); + method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int); method public void setLetterSpacing(float); - method public void setLineHeight(@Px @IntRange(from=0) int); + method public void setLineHeight(@IntRange(from=0) @Px int); method public void setLineSpacing(float, float); method public void setLines(int); method public final void setLinkTextColor(@ColorInt int); @@ -60715,7 +60718,7 @@ package java.lang { ctor public OutOfMemoryError(String); } - @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface Override { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface Override { } public class Package implements java.lang.reflect.AnnotatedElement { @@ -61219,7 +61222,7 @@ package java.lang { ctor public StringIndexOutOfBoundsException(int); } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface SuppressWarnings { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressWarnings { method public abstract String[] value(); } diff --git a/api/system-current.txt b/api/system-current.txt index 1b431a2f4800..3e2d01f1d5a4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -391,7 +391,7 @@ package android.app { field public static final int UID_STATE_CACHED = 700; // 0x2bc field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4 field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190 - field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c + field @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c field public static final int UID_STATE_PERSISTENT = 100; // 0x64 field public static final int UID_STATE_TOP = 200; // 0xc8 } @@ -602,7 +602,7 @@ package android.app { method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException; method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException; method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException; method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent); @@ -1391,7 +1391,7 @@ package android.content { method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle); 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_FULL) public void startActivityAsUser(@RequiresPermission @NonNull android.content.Intent, @NonNull android.os.UserHandle); + method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle); field public static final String APP_PREDICTION_SERVICE = "app_prediction"; field public static final String BACKUP_SERVICE = "backup"; field public static final String BATTERY_STATS_SERVICE = "batterystats"; @@ -1884,8 +1884,8 @@ package android.content.rollback { public final class RollbackManager { method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; field public static final int STATUS_FAILURE = 1; // 0x1 @@ -2396,24 +2396,24 @@ package android.hardware.location { } public final class ContextHubManager { - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] findNanoAppOnHub(int, @NonNull android.hardware.location.NanoAppFilter); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] getContextHubHandles(); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubInfo getContextHubInfo(int); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs(); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int loadNanoApp(int, @NonNull android.hardware.location.NanoApp); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo); method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback); method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int unloadNanoApp(int); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback); field public static final int EVENT_HUB_RESET = 6; // 0x6 field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4 @@ -3099,7 +3099,7 @@ package android.hardware.usb { } public final class UsbPort { - method @RequiresPermission(android.Manifest.permission.MANAGE_USB) @Nullable public android.hardware.usb.UsbPortStatus getStatus(); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int); } @@ -3497,7 +3497,7 @@ package android.location { method @NonNull public android.location.LocationRequest setFastestInterval(long); method public void setHideFromAppOps(boolean); method @NonNull public android.location.LocationRequest setInterval(long); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean); method @NonNull public android.location.LocationRequest setLowPowerMode(boolean); method @NonNull public android.location.LocationRequest setNumUpdates(int); method @NonNull public android.location.LocationRequest setProvider(@NonNull String); @@ -3828,7 +3828,7 @@ package android.media.soundtrigger { method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID); method public int getDetectionServiceOperationsTimeout(); method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID); - method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Nullable public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties(); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties(); method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model); } @@ -4516,7 +4516,8 @@ package android.net.util { method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); } } @@ -5239,7 +5240,7 @@ package android.os { } public class BatteryStatsManager { - method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) @NonNull public android.os.connectivity.WifiBatteryStats getWifiBatteryStats(); + method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats(); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiBatchedScanStartedFromSource(@NonNull android.os.WorkSource, @IntRange(from=0) int); @@ -5459,8 +5460,8 @@ package android.os { method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public java.util.List<android.net.Uri> getIncidentReportList(String); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports(); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs); method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener); @@ -5691,6 +5692,7 @@ package android.os { method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle); method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability(); method public boolean hasRestrictedProfiles(); + 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(android.Manifest.permission.MANAGE_USERS) public boolean isAdminUser(); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isGuestUser(); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedProfile(); @@ -6010,7 +6012,7 @@ package android.provider { field public static final String NAMESPACE_AUTOFILL = "autofill"; field public static final String NAMESPACE_CONNECTIVITY = "connectivity"; field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; - field public static final String NAMESPACE_DEX_BOOT = "dex_boot"; + field @Deprecated public static final String NAMESPACE_DEX_BOOT = "dex_boot"; field public static final String NAMESPACE_DISPLAY_MANAGER = "display_manager"; field public static final String NAMESPACE_GAME_DRIVER = "game_driver"; field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot"; @@ -6278,7 +6280,7 @@ package android.provider { field public static final String MESSAGE_BODY = "body"; field public static final String MESSAGE_BROADCASTED = "message_broadcasted"; field public static final String MESSAGE_FORMAT = "format"; - field @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) @NonNull public static final android.net.Uri MESSAGE_HISTORY_URI; + field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI; field public static final String MESSAGE_PRIORITY = "priority"; field public static final String MESSAGE_READ = "read"; field public static final String PLMN = "plmn"; @@ -6309,7 +6311,7 @@ package android.provider { package android.security.keystore { public abstract class AttestationUtils { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @NonNull public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; field public static final int ID_TYPE_IMEI = 2; // 0x2 field public static final int ID_TYPE_MEID = 3; // 0x3 field public static final int ID_TYPE_SERIAL = 1; // 0x1 @@ -6390,18 +6392,18 @@ package android.security.keystore.recovery { } public class RecoveryController { - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public android.security.keystore.recovery.RecoverySession createRecoverySession(); + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public android.security.keystore.recovery.RecoverySession createRecoverySession(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key generateKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.security.Key generateKey(@NonNull String, @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public static android.security.keystore.recovery.RecoveryController getInstance(@NonNull android.content.Context); - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @Nullable public java.security.Key getKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @Nullable public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key generateKey(@NonNull String, @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public static android.security.keystore.recovery.RecoveryController getInstance(@NonNull android.content.Context); + method @Nullable @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key getKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException; + method @Nullable @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException; method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException; method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public int getRecoveryStatus(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.Map<java.lang.String,java.security.cert.X509Certificate> getRootCertificates(); + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.Map<java.lang.String,java.security.cert.X509Certificate> getRootCertificates(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key importKey(@NonNull String, @NonNull byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.security.Key importKey(@NonNull String, @NonNull byte[], @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key importKey(@NonNull String, @NonNull byte[], @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void initRecoveryService(@NonNull String, @NonNull byte[], @NonNull byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public static boolean isRecoverableKeyStoreEnabled(@NonNull android.content.Context); method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void removeKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException; @@ -6416,8 +6418,8 @@ package android.security.keystore.recovery { public class RecoverySession implements java.lang.AutoCloseable { method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void close(); - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.Map<java.lang.String,java.security.Key> recoverKeyChainSnapshot(@NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public byte[] start(@NonNull String, @NonNull java.security.cert.CertPath, @NonNull byte[], @NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.Map<java.lang.String,java.security.Key> recoverKeyChainSnapshot(@NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public byte[] start(@NonNull String, @NonNull java.security.cert.CertPath, @NonNull byte[], @NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; } public class SessionExpiredException extends java.security.GeneralSecurityException { @@ -6560,7 +6562,29 @@ package android.service.carrier { public abstract class ApnService extends android.app.Service { ctor public ApnService(); method @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent); - method @WorkerThread @NonNull public abstract java.util.List<android.content.ContentValues> onRestoreApns(int); + method @NonNull @WorkerThread public abstract java.util.List<android.content.ContentValues> onRestoreApns(int); + } + + public abstract class CarrierMessagingServiceWrapper { + ctor public CarrierMessagingServiceWrapper(); + method public boolean bindToCarrierMessagingService(@NonNull android.content.Context, @NonNull String); + method public void disposeConnection(@NonNull android.content.Context); + method public void downloadMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void filterSms(@NonNull android.service.carrier.MessagePdu, @NonNull String, int, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public abstract void onServiceReady(); + method public void sendDataSms(@NonNull byte[], int, @NonNull String, int, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void sendMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void sendMultipartTextSms(@NonNull java.util.List<java.lang.String>, int, @NonNull String, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void sendTextSms(@NonNull String, int, @NonNull String, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + } + + public abstract static class CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper { + ctor public CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper(); + method public void onDownloadMmsComplete(int); + method public void onFilterComplete(int); + method public void onSendMmsComplete(int, @Nullable byte[]); + method public void onSendMultipartSmsComplete(int, @Nullable int[]); + method public void onSendSmsComplete(int, int); } } @@ -6672,13 +6696,13 @@ package android.service.euicc { method public android.service.euicc.EuiccProfileInfo.Builder setUiccAccessRule(@Nullable java.util.List<android.telephony.UiccAccessRule>); } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"POLICY_RULE_"}, value={android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DELETE_AFTER_DISABLING}) public static @interface EuiccProfileInfo.PolicyRule { + @IntDef(flag=true, prefix={"POLICY_RULE_"}, value={android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DELETE_AFTER_DISABLING}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.PolicyRule { } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"PROFILE_CLASS_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_TESTING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, 0xffffffff}) public static @interface EuiccProfileInfo.ProfileClass { + @IntDef(prefix={"PROFILE_CLASS_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_TESTING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, 0xffffffff}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.ProfileClass { } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"PROFILE_STATE_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_STATE_DISABLED, android.service.euicc.EuiccProfileInfo.PROFILE_STATE_ENABLED, 0xffffffff}) public static @interface EuiccProfileInfo.ProfileState { + @IntDef(prefix={"PROFILE_STATE_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_STATE_DISABLED, android.service.euicc.EuiccProfileInfo.PROFILE_STATE_ENABLED, 0xffffffff}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.ProfileState { } public abstract class EuiccService extends android.app.Service { @@ -6857,7 +6881,7 @@ package android.service.notification { package android.service.oemlock { public class OemLockManager { - method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) @Nullable public String getLockName(); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public String getLockName(); method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public boolean isOemUnlockAllowedByCarrier(); method @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE) public boolean isOemUnlockAllowedByUser(); method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public void setOemUnlockAllowedByCarrier(boolean, @Nullable byte[]); @@ -6870,7 +6894,7 @@ package android.service.persistentdata { public class PersistentDataBlockManager { method @RequiresPermission("android.permission.ACCESS_PDB_STATE") public int getDataBlockSize(); - method @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) @android.service.persistentdata.PersistentDataBlockManager.FlashLockState public int getFlashLockState(); + method @android.service.persistentdata.PersistentDataBlockManager.FlashLockState @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) public int getFlashLockState(); method public long getMaximumDataBlockSize(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) public boolean getOemUnlockEnabled(); method public byte[] read(); @@ -7462,6 +7486,7 @@ package android.telephony { ctor public CellBroadcastService(); method @CallSuper public android.os.IBinder onBind(android.content.Intent); method public abstract void onCdmaCellBroadcastSms(int, byte[], int); + method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>); method public abstract void onGsmCellBroadcastSms(int, byte[]); field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService"; } @@ -7893,6 +7918,14 @@ package android.telephony { field public static final int WIFI_LOST = 59; // 0x3b } + public final class ImsiEncryptionInfo implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public String getKeyIdentifier(); + method @Nullable public java.security.PublicKey getPublicKey(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR; + } + public final class LteVopsSupportInfo implements android.os.Parcelable { ctor public LteVopsSupportInfo(int, int); method public int describeContents(); @@ -8377,6 +8410,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset(int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); @@ -8430,6 +8464,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); 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 requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); @@ -8453,6 +8488,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); 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"; + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED"; field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; @@ -8465,6 +8501,8 @@ package android.telephony { field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; + field public static final int KEY_TYPE_EPDG = 1; // 0x1 + field public static final int KEY_TYPE_WLAN = 2; // 0x2 field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L @@ -8756,10 +8794,10 @@ package android.telephony.euicc { field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) public static @interface EuiccCardManager.CancelReason { + @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason { } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) public static @interface EuiccCardManager.ResetOption { + @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption { } public static interface EuiccCardManager.ResultCallback<T> { @@ -8815,7 +8853,7 @@ package android.telephony.euicc { field public static final int EVENT_INSTALL = 1; // 0x1 } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) public static @interface EuiccNotification.Event { + @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event { } public final class EuiccRulesAuthTable implements android.os.Parcelable { @@ -8833,7 +8871,7 @@ package android.telephony.euicc { method public android.telephony.euicc.EuiccRulesAuthTable build(); } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) public static @interface EuiccRulesAuthTable.PolicyRuleFlag { + @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag { } } @@ -9492,12 +9530,12 @@ package android.telephony.ims { public class ProvisioningManager { method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int); - method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getProvisioningIntValue(int); - method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); - method @WorkerThread @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b diff --git a/api/test-current.txt b/api/test-current.txt index 5b167432373f..495e57af1990 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -71,6 +71,9 @@ package android.app { method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int); + field public static final int PROCESS_CAPABILITY_ALL = 1; // 0x1 + field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1 + field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0 } public static interface ActivityManager.OnUidImportanceListener { @@ -233,7 +236,7 @@ package android.app { field public static final int UID_STATE_CACHED = 700; // 0x2bc field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4 field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190 - field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c + field @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c field public static final int UID_STATE_PERSISTENT = 100; // 0x64 field public static final int UID_STATE_TOP = 200; // 0xc8 } @@ -852,8 +855,8 @@ package android.content.rollback { method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; @@ -1148,7 +1151,7 @@ package android.location { method @NonNull public android.location.LocationRequest setExpireIn(long); method @NonNull public android.location.LocationRequest setFastestInterval(long); method @NonNull public android.location.LocationRequest setInterval(long); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean); method @NonNull public android.location.LocationRequest setLowPowerMode(boolean); method @NonNull public android.location.LocationRequest setNumUpdates(int); method @NonNull public android.location.LocationRequest setProvider(@NonNull String); @@ -1725,7 +1728,8 @@ package android.net.util { method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); } } @@ -1923,8 +1927,8 @@ package android.os { method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public java.util.List<android.net.Uri> getIncidentReportList(String); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports(); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs); method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener); @@ -2422,6 +2426,7 @@ package android.provider { } public static final class Settings.Global extends android.provider.Settings.NameValueTable { + field public static final String APP_OPS_CONSTANTS = "app_ops_constants"; field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages"; field public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode"; field public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants"; @@ -2481,7 +2486,7 @@ package android.provider { field public static final String MESSAGE_BODY = "body"; field public static final String MESSAGE_BROADCASTED = "message_broadcasted"; field public static final String MESSAGE_FORMAT = "format"; - field @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) @NonNull public static final android.net.Uri MESSAGE_HISTORY_URI; + field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI; field public static final String MESSAGE_PRIORITY = "priority"; field public static final String MESSAGE_READ = "read"; field public static final String PLMN = "plmn"; @@ -2513,7 +2518,7 @@ package android.security { package android.security.keystore { public abstract class AttestationUtils { - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; + method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; field public static final int ID_TYPE_IMEI = 2; // 0x2 field public static final int ID_TYPE_MEID = 3; // 0x3 field public static final int ID_TYPE_SERIAL = 1; // 0x1 diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 6fd03273a434..0ee156b07c55 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -650,6 +650,7 @@ bool getDoubleOrLong(const LogEvent& event, const Matcher& matcher, Value& ret) ret.setDouble(value.mValue.double_value); break; default: + return false; break; } return true; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 7f597fef807a..1e78fc143888 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -163,7 +163,7 @@ public class ActivityManager { } @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) { + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportanceForClient( procState, mContext)); } @@ -432,7 +432,6 @@ public class ActivityManager { public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4; /** - * @hide * Process states, describing the kind of state a particular process is in. * When updating these, make sure to also check all related references to the * constant in code, and update these arrays: @@ -443,7 +442,34 @@ public class ActivityManager { * @see com.android.server.am.ProcessList#sSameAwakePssTimes * @see com.android.server.am.ProcessList#sTestFirstPssTimes * @see com.android.server.am.ProcessList#sTestSamePssTimes + * @hide */ + @IntDef(flag = false, prefix = { "PROCESS_STATE_" }, value = { + PROCESS_STATE_UNKNOWN, // -1 + PROCESS_STATE_PERSISTENT, // 0 + PROCESS_STATE_PERSISTENT_UI, + PROCESS_STATE_TOP, + PROCESS_STATE_BOUND_TOP, + PROCESS_STATE_FOREGROUND_SERVICE, + PROCESS_STATE_BOUND_FOREGROUND_SERVICE, + PROCESS_STATE_IMPORTANT_FOREGROUND, + PROCESS_STATE_IMPORTANT_BACKGROUND, + PROCESS_STATE_TRANSIENT_BACKGROUND, + PROCESS_STATE_BACKUP, + PROCESS_STATE_SERVICE, + PROCESS_STATE_RECEIVER, + PROCESS_STATE_TOP_SLEEPING, + PROCESS_STATE_HEAVY_WEIGHT, + PROCESS_STATE_HOME, + PROCESS_STATE_LAST_ACTIVITY, + PROCESS_STATE_CACHED_ACTIVITY, + PROCESS_STATE_CACHED_ACTIVITY_CLIENT, + PROCESS_STATE_CACHED_RECENT, + PROCESS_STATE_CACHED_EMPTY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ProcessState {} + /** @hide Not a real process state. */ public static final int PROCESS_STATE_UNKNOWN = -1; @@ -459,78 +485,98 @@ public class ActivityManager { @UnsupportedAppUsage public static final int PROCESS_STATE_TOP = 2; - /** @hide Process is hosting a foreground service with location type. */ - public static final int PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3; - /** @hide Process is bound to a TOP app. This is ranked below SERVICE_LOCATION so that * it doesn't get the capability of location access while-in-use. */ - public static final int PROCESS_STATE_BOUND_TOP = 4; + public static final int PROCESS_STATE_BOUND_TOP = 3; /** @hide Process is hosting a foreground service. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_FOREGROUND_SERVICE = 5; + public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; /** @hide Process is hosting a foreground service due to a system binding. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6; + public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5; /** @hide Process is important to the user, and something they are aware of. */ - public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 7; + public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6; /** @hide Process is important to the user, but not something they are aware of. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 8; + public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7; /** @hide Process is in the background transient so we will try to keep running. */ - public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 9; + public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 8; /** @hide Process is in the background running a backup/restore operation. */ - public static final int PROCESS_STATE_BACKUP = 10; + public static final int PROCESS_STATE_BACKUP = 9; /** @hide Process is in the background running a service. Unlike oom_adj, this level * is used for both the normal running in background state and the executing * operations state. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_SERVICE = 11; + public static final int PROCESS_STATE_SERVICE = 10; /** @hide Process is in the background running a receiver. Note that from the * perspective of oom_adj, receivers run at a higher foreground level, but for our * prioritization here that is not necessary and putting them below services means * many fewer changes in some process states as they receive broadcasts. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_RECEIVER = 12; + public static final int PROCESS_STATE_RECEIVER = 11; /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */ - public static final int PROCESS_STATE_TOP_SLEEPING = 13; + public static final int PROCESS_STATE_TOP_SLEEPING = 12; /** @hide Process is in the background, but it can't restore its state so we want * to try to avoid killing it. */ - public static final int PROCESS_STATE_HEAVY_WEIGHT = 14; + public static final int PROCESS_STATE_HEAVY_WEIGHT = 13; /** @hide Process is in the background but hosts the home activity. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_HOME = 15; + public static final int PROCESS_STATE_HOME = 14; /** @hide Process is in the background but hosts the last shown activity. */ - public static final int PROCESS_STATE_LAST_ACTIVITY = 16; + public static final int PROCESS_STATE_LAST_ACTIVITY = 15; /** @hide Process is being cached for later use and contains activities. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_CACHED_ACTIVITY = 17; + public static final int PROCESS_STATE_CACHED_ACTIVITY = 16; /** @hide Process is being cached for later use and is a client of another cached * process that contains activities. */ - public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18; + public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17; /** @hide Process is being cached for later use and has an activity that corresponds * to an existing recent task. */ - public static final int PROCESS_STATE_CACHED_RECENT = 19; + public static final int PROCESS_STATE_CACHED_RECENT = 18; /** @hide Process is being cached for later use and is empty. */ - public static final int PROCESS_STATE_CACHED_EMPTY = 20; + public static final int PROCESS_STATE_CACHED_EMPTY = 19; /** @hide Process does not exist. */ - public static final int PROCESS_STATE_NONEXISTENT = 21; + public static final int PROCESS_STATE_NONEXISTENT = 20; + + /** + * The set of flags for process capability. + * @hide + */ + @IntDef(flag = true, prefix = { "PROCESS_CAPABILITY_" }, value = { + PROCESS_CAPABILITY_NONE, + PROCESS_CAPABILITY_FOREGROUND_LOCATION, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ProcessCapability {} + + /** @hide Process does not have any capability */ + @TestApi + public static final int PROCESS_CAPABILITY_NONE = 0; + + /** @hide Process can access location while in foreground */ + @TestApi + public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 0; + + /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/ + @TestApi + public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION; // NOTE: If PROCESS_STATEs are added, then new fields must be added // to frameworks/base/core/proto/android/app/enums.proto and the following method must @@ -557,7 +603,6 @@ public class ActivityManager { return AppProtoEnums.PROCESS_STATE_TOP; case PROCESS_STATE_BOUND_TOP: return AppProtoEnums.PROCESS_STATE_BOUND_TOP; - case PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: case PROCESS_STATE_FOREGROUND_SERVICE: return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE; case PROCESS_STATE_BOUND_FOREGROUND_SERVICE: @@ -612,8 +657,7 @@ public class ActivityManager { /** @hide Is this a foreground service type? */ public static boolean isForegroundService(int procState) { - return procState == PROCESS_STATE_FOREGROUND_SERVICE_LOCATION - || procState == PROCESS_STATE_FOREGROUND_SERVICE; + return procState == PROCESS_STATE_FOREGROUND_SERVICE; } /** @hide requestType for assist context: only basic information. */ @@ -2930,7 +2974,7 @@ public class ActivityManager { return IMPORTANCE_PERCEPTIBLE; } else if (procState >= PROCESS_STATE_IMPORTANT_FOREGROUND) { return IMPORTANCE_VISIBLE; - } else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) { + } else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE) { return IMPORTANCE_FOREGROUND_SERVICE; } else { return IMPORTANCE_FOREGROUND; @@ -4087,7 +4131,7 @@ public class ActivityManager { * Action an app can implement to handle reports from {@link #setWatchHeapLimit(long)}. * If your package has an activity handling this action, it will be launched with the * heap data provided to it the same way as {@link Intent#ACTION_SEND}. Note that to - * match the activty must support this action and a MIME type of "*/*". + * match, the activity must support this action and a MIME type of "*/*". */ public static final String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT"; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 8bca87e69ecc..765c358748a3 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -282,10 +282,14 @@ public class AppOpsManager { /** * Uid state: The UID is running a foreground service of location type. * The lower the UID state the more important the UID is for the user. + * This uid state is a counterpart to PROCESS_STATE_FOREGROUND_SERVICE_LOCATION which has been + * deprecated. * @hide + * @deprecated */ @TestApi @SystemApi + @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; /** @@ -298,13 +302,6 @@ public class AppOpsManager { public static final int UID_STATE_FOREGROUND_SERVICE = 400; /** - * The max, which is min priority, UID state for which any app op - * would be considered as performed in the foreground. - * @hide - */ - public static final int UID_STATE_MAX_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND_SERVICE; - - /** * Uid state: The UID is a foreground app. The lower the UID * state the more important the UID is for the user. * @hide @@ -314,6 +311,13 @@ public class AppOpsManager { public static final int UID_STATE_FOREGROUND = 500; /** + * The max, which is min priority, UID state for which any app op + * would be considered as performed in the foreground. + * @hide + */ + public static final int UID_STATE_MAX_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND; + + /** * Uid state: The UID is a background app. The lower the UID * state the more important the UID is for the user. * @hide @@ -344,47 +348,25 @@ public class AppOpsManager { public static final int MIN_PRIORITY_UID_STATE = UID_STATE_CACHED; /** - * Resolves the first unrestricted state given an app op. Location is - * special as we want to allow its access only if a dedicated location - * foreground service is running. For other ops we consider any foreground - * service as a foreground state. - * + * Resolves the first unrestricted state given an app op. * @param op The op to resolve. * @return The last restricted UID state. * * @hide */ public static int resolveFirstUnrestrictedUidState(int op) { - switch (op) { - case OP_FINE_LOCATION: - case OP_COARSE_LOCATION: - case OP_MONITOR_LOCATION: - case OP_MONITOR_HIGH_POWER_LOCATION: { - return UID_STATE_FOREGROUND_SERVICE_LOCATION; - } - } - return UID_STATE_FOREGROUND_SERVICE; + return UID_STATE_FOREGROUND; } /** - * Resolves the last restricted state given an app op. Location is - * special as we want to allow its access only if a dedicated location - * foreground service is running. For other ops we consider any foreground - * service as a foreground state. - * + * Resolves the last restricted state given an app op. * @param op The op to resolve. * @return The last restricted UID state. * * @hide */ public static int resolveLastRestrictedUidState(int op) { - switch (op) { - case OP_FINE_LOCATION: - case OP_COARSE_LOCATION: { - return UID_STATE_FOREGROUND_SERVICE; - } - } - return UID_STATE_FOREGROUND; + return UID_STATE_BACKGROUND; } /** @hide Note: Keep these sorted */ @@ -4603,7 +4585,6 @@ public class AppOpsManager { * * @param fromUidState The UID state from which to query. Could be one of * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP}, - * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION}, * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND}, * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}. * @param toUidState The UID state to which to query. @@ -4664,7 +4645,6 @@ public class AppOpsManager { * * @param fromUidState The UID state from which to query. Could be one of * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP}, - * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION}, * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND}, * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}. * @param toUidState The UID state to which to query. @@ -4728,7 +4708,6 @@ public class AppOpsManager { * * @param fromUidState The UID state from which to query. Could be one of * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP}, - * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION}, * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND}, * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}. * @param toUidState The UID state from which to query. diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl index e116d989ca75..7713e25d5ecd 100644 --- a/core/java/android/app/IUidObserver.aidl +++ b/core/java/android/app/IUidObserver.aidl @@ -50,8 +50,9 @@ oneway interface IUidObserver { * @param procState The updated process state for the uid. * @param procStateSeq The sequence no. associated with process state change of the uid, * see UidRecord.procStateSeq for details. + * @param capability the updated process capability for the uid. */ - void onUidStateChanged(int uid, int procState, long procStateSeq); + void onUidStateChanged(int uid, int procState, long procStateSeq, int capability); // =============== End of transactions used on native side as well ============================ diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 6a13499f0444..629c2bb19a7c 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -23,6 +23,7 @@ import android.app.admin.DevicePolicyManager; import android.app.admin.IDevicePolicyManager; import android.app.contentsuggestions.ContentSuggestionsManager; import android.app.contentsuggestions.IContentSuggestionsManager; +import android.app.job.JobSchedulerFrameworkInitializer; import android.app.prediction.AppPredictionManager; import android.app.role.RoleControllerManager; import android.app.role.RoleManager; @@ -153,7 +154,6 @@ import android.os.health.SystemHealthManager; import android.os.image.DynamicSystemManager; import android.os.image.IDynamicSystemService; import android.os.storage.StorageManager; -import android.telephony.TelephonyRegistryManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; @@ -167,6 +167,7 @@ import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.telephony.TelephonyRegistryManager; import android.telephony.euicc.EuiccCardManager; import android.telephony.euicc.EuiccManager; import android.telephony.ims.RcsMessageManager; @@ -1298,6 +1299,9 @@ public final class SystemServiceRegistry { IBatteryStats.Stub.asInterface(b)); }}); //CHECKSTYLE:ON IndentationCheck + + JobSchedulerFrameworkInitializer.initialize(); + DeviceIdleFrameworkInitializer.initialize(); } /** diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java index 489a2922f70e..e9ea99f84f90 100644 --- a/core/java/android/net/util/SocketUtils.java +++ b/core/java/android/net/util/SocketUtils.java @@ -77,7 +77,9 @@ public final class SocketUtils { /** * Make a socket address that packet socket can send packets to. + * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead. */ + @Deprecated @NonNull public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) { return new PacketSocketAddress( @@ -87,6 +89,18 @@ public final class SocketUtils { } /** + * Make a socket address that packet socket can send packets to. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex, + @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + + /** * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor) */ public static void closeSocket(@Nullable FileDescriptor fd) throws IOException { diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index af0ec1188bc7..fa09cf0bb4e3 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -17,7 +17,6 @@ package android.os; import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; -import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; import android.annotation.IntDef; import android.annotation.UnsupportedAppUsage; @@ -923,7 +922,6 @@ public abstract class BatteryStats implements Parcelable { */ public static final int[] CRITICAL_PROC_STATES = { PROCESS_STATE_TOP, - PROCESS_STATE_FOREGROUND_SERVICE_LOCATION, PROCESS_STATE_BOUND_TOP, PROCESS_STATE_FOREGROUND_SERVICE, PROCESS_STATE_FOREGROUND }; diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index b7a3c8f2f3be..3476b18ceee0 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1909,7 +1909,14 @@ public class UserManager { * Returns the user-wide restrictions imposed on the user specified by <code>userHandle</code>. * @param userHandle the UserHandle of the user for whom to retrieve the restrictions. * @return a Bundle containing all the restrictions. + * + * <p>Requires {@code android.permission.MANAGE_USERS} or + * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user} + * must be the calling user or a managed profile associated with it. */ + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true) public Bundle getUserRestrictions(UserHandle userHandle) { try { return mService.getUserRestrictions(userHandle.getIdentifier()); @@ -2000,7 +2007,7 @@ public class UserManager { * @return {@code true} if the current user has the given restriction, {@code false} otherwise. */ public boolean hasUserRestriction(String restrictionKey) { - return hasUserRestriction(restrictionKey, Process.myUserHandle()); + return hasUserRestrictionForUser(restrictionKey, Process.myUserHandle()); } /** @@ -2012,9 +2019,29 @@ public class UserManager { */ @UnsupportedAppUsage public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) { + return hasUserRestrictionForUser(restrictionKey, userHandle); + } + + /** + * Returns whether the given user has been disallowed from performing certain actions + * or setting certain settings. + * @param restrictionKey the string key representing the restriction + * @param userHandle the UserHandle of the user for whom to retrieve the restrictions. + * + * <p>Requires {@code android.permission.MANAGE_USERS} or + * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user} + * must be the calling user or a managed profile associated with it. + * + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true) + public boolean hasUserRestrictionForUser(@NonNull String restrictionKey, + @NonNull UserHandle userHandle) { try { - return mService.hasUserRestriction(restrictionKey, - userHandle.getIdentifier()); + return mService.hasUserRestriction(restrictionKey, userHandle.getIdentifier()); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index bb8b041f6b46..0401d7fb8d5d 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -130,8 +130,10 @@ public final class DeviceConfig { /** * Namespace for how dex runs. The feature requires a reboot to reach a clean state. * + * @deprecated No longer used * @hide */ + @Deprecated @SystemApi public static final String NAMESPACE_DEX_BOOT = "dex_boot"; diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 4153831584e9..aa67d9779da4 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -2040,6 +2040,10 @@ public final class MediaStore { * generated. Callers are responsible for their own in-memory * caching of returned values. * + * As of {@link android.os.Build.VERSION_CODES#Q}, this output + * of the thumbnail has correct rotation, don't need to rotate + * it again. + * * @param imageId the image item to obtain a thumbnail for. * @param kind optimal thumbnail size desired. * @return decoded thumbnail, or {@code null} if problem was @@ -2082,6 +2086,10 @@ public final class MediaStore { * generated. Callers are responsible for their own in-memory * caching of returned values. * + * As of {@link android.os.Build.VERSION_CODES#Q}, this output + * of the thumbnail has correct rotation, don't need to rotate + * it again. + * * @param imageId the image item to obtain a thumbnail for. * @param kind optimal thumbnail size desired. * @return decoded thumbnail, or {@code null} if problem was @@ -2136,6 +2144,9 @@ public final class MediaStore { * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain * access. * + * As of {@link android.os.Build.VERSION_CODES#Q}, this thumbnail + * has correct rotation, don't need to rotate it again. + * * @deprecated Apps may not have filesystem permissions to directly * access this path. Instead of trying to open this path * directly, apps should use diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 44ab09ed8ad4..381d4921932f 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10654,6 +10654,7 @@ public final class Settings { * @hide * @see com.android.server.AppOpsService.Constants */ + @TestApi public static final String APP_OPS_CONSTANTS = "app_ops_constants"; /** diff --git a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java new file mode 100644 index 000000000000..de90b94d7535 --- /dev/null +++ b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.carrier; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.IBinder; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +import java.util.List; + +/** + * Provides basic structure for platform to connect to the carrier messaging service. + * <p> + * <code> + * CarrierMessagingServiceWrapper carrierMessagingServiceWrapper = + * new CarrierMessagingServiceWrapperImpl(); + * if (carrierMessagingServiceWrapper.bindToCarrierMessagingService(context, carrierPackageName)) { + * // wait for onServiceReady callback + * } else { + * // Unable to bind: handle error. + * } + * </code> + * <p> Upon completion {@link #disposeConnection} should be called to unbind the + * CarrierMessagingService. + * @hide + */ +@SystemApi +public abstract class CarrierMessagingServiceWrapper { + // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete + // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized. + private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection; + + private volatile ICarrierMessagingService mICarrierMessagingService; + + /** + * Binds to the carrier messaging service under package {@code carrierPackageName}. This method + * should be called exactly once. + * + * @param context the context + * @param carrierPackageName the carrier package name + * @return true upon successfully binding to a carrier messaging service, false otherwise + * @hide + */ + @SystemApi + public boolean bindToCarrierMessagingService(@NonNull Context context, + @NonNull String carrierPackageName) { + Preconditions.checkState(mCarrierMessagingServiceConnection == null); + + Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE); + intent.setPackage(carrierPackageName); + mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection(); + return context.bindService(intent, mCarrierMessagingServiceConnection, + Context.BIND_AUTO_CREATE); + } + + /** + * Unbinds the carrier messaging service. This method should be called exactly once. + * + * @param context the context + * @hide + */ + @SystemApi + public void disposeConnection(@NonNull Context context) { + Preconditions.checkNotNull(mCarrierMessagingServiceConnection); + context.unbindService(mCarrierMessagingServiceConnection); + mCarrierMessagingServiceConnection = null; + } + + /** + * Implemented by subclasses to use the carrier messaging service once it is ready. + * @hide + */ + @SystemApi + public abstract void onServiceReady(); + + /** + * Called when connection with service is established. + * + * @param carrierMessagingService the carrier messaing service interface + */ + private void onServiceReady(ICarrierMessagingService carrierMessagingService) { + mICarrierMessagingService = carrierMessagingService; + onServiceReady(); + } + + /** + * Request filtering an incoming SMS message. + * The service will call callback.onFilterComplete with the filtering result. + * + * @param pdu the PDUs of the message + * @param format the format of the PDUs, typically "3gpp" or "3gpp2" + * @param destPort the destination port of a data SMS. It will be -1 for text SMS + * @param subId SMS subscription ID of the SIM + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void filterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort, + int subId, @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.filterSms(pdu, format, destPort, subId, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new text SMS from the device. + * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send + * status. + * + * @param text the text to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag flag for sending SMS + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress, + int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new data SMS from the device. + * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send + * status. + * + * @param data the data to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param destPort port number of the recipient of the message + * @param sendSmsFlag flag for sending SMS + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress, + int destPort, int sendSmsFlag, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort, + sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new multi-part text SMS from the device. + * The service will call {@link ICarrierMessagingCallback#onSendMultipartSmsComplete} + * with the send status. + * + * @param parts the parts of the multi-part text SMS to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag flag for sending SMS + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendMultipartTextSms(@NonNull List<String> parts, int subId, + @NonNull String destAddress, int sendSmsFlag, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress, + sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new MMS PDU from the device. + * The service will call {@link ICarrierMessagingCallback#onSendMmsComplete} with the send + * status. + * + * @param pduUri the content provider URI of the PDU to send + * @param subId SMS subscription ID of the SIM + * @param location the optional URI to send this MMS PDU. If this is {code null}, + * the PDU should be sent to the default MMSC URL. + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendMms(pduUri, subId, location, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request downloading a new MMS. + * The service will call {@link ICarrierMessagingCallback#onDownloadMmsComplete} with the + * download status. + * + * @param pduUri the content provider URI of the PDU to be downloaded. + * @param subId SMS subscription ID of the SIM + * @param location the URI of the message to be downloaded. + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.downloadMms(pduUri, subId, location, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * A basic {@link ServiceConnection}. + */ + private final class CarrierMessagingServiceConnection implements ServiceConnection { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + onServiceReady(ICarrierMessagingService.Stub.asInterface(service)); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + } + + /** + * Callback wrapper used for response to requests exposed by + * {@link CarrierMessagingServiceWrapper}. + * @hide + */ + @SystemApi + public abstract static class CarrierMessagingCallbackWrapper { + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#filterSms}. + * @param result a bitmask integer to indicate how the incoming text SMS should be handled + * by the platform. Bits set can be + * {@link CarrierMessagingService#RECEIVE_OPTIONS_DROP} and + * {@link CarrierMessagingService# + * RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}. + * {@see CarrierMessagingService#onReceiveTextSms}. + * @hide + */ + @SystemApi + public void onFilterComplete(int result) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#sendTextSms} and + * {@link CarrierMessagingServiceWrapper#sendDataSms}. + * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @param messageRef message reference of the just-sent message. This field is applicable + * only if result is {@link CarrierMessagingService#SEND_STATUS_OK}. + * @hide + */ + @SystemApi + public void onSendSmsComplete(int result, int messageRef) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#sendMultipartTextSms}. + * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @param messageRefs an array of message references, one for each part of the + * multipart SMS. This field is applicable only if result is + * {@link CarrierMessagingService#SEND_STATUS_OK}. + * @hide + */ + @SystemApi + public void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#sendMms}. + * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message + * was sent. sendConfPdu is ignored if the {@code result} is not + * {@link CarrierMessagingService#SEND_STATUS_OK}. + * @hide + */ + @SystemApi + public void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#downloadMms}. + * @param result download status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @hide + */ + @SystemApi + public void onDownloadMmsComplete(int result) { + + } + } + + private final class CarrierMessagingCallbackWrapperInternal + extends ICarrierMessagingCallback.Stub { + CarrierMessagingCallbackWrapper mCarrierMessagingCallbackWrapper; + + CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback) { + mCarrierMessagingCallbackWrapper = callback; + } + + @Override + public void onFilterComplete(int result) throws RemoteException { + mCarrierMessagingCallbackWrapper.onFilterComplete(result); + } + + @Override + public void onSendSmsComplete(int result, int messageRef) throws RemoteException { + mCarrierMessagingCallbackWrapper.onSendSmsComplete(result, messageRef); + } + + @Override + public void onSendMultipartSmsComplete(int result, int[] messageRefs) + throws RemoteException { + mCarrierMessagingCallbackWrapper.onSendMultipartSmsComplete(result, messageRefs); + } + + @Override + public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException { + mCarrierMessagingCallbackWrapper.onSendMmsComplete(result, sendConfPdu); + } + + @Override + public void onDownloadMmsComplete(int result) throws RemoteException { + mCarrierMessagingCallbackWrapper.onDownloadMmsComplete(result); + } + } +} diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java index 91a5ec0303f7..8d9607ff11e2 100644 --- a/core/java/android/util/StatsEvent.java +++ b/core/java/android/util/StatsEvent.java @@ -20,312 +20,540 @@ import static java.nio.charset.StandardCharsets.UTF_8; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.SystemClock; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; /** * StatsEvent builds and stores the buffer sent over the statsd socket. * This class defines and encapsulates the socket protocol. + * + * <p>Usage:</p> + * <pre> + * StatsEvent statsEvent = StatsEvent.newBuilder() + * .setAtomId(atomId) + * .writeBoolean(false) + * .writeString("annotated String field") + * .addBooleanAnnotation(annotationId, true) + * .build(); + * + * StatsLog.write(statsEvent); + * </pre> * @hide **/ -public final class StatsEvent implements AutoCloseable { - private static final int POS_NUM_ELEMENTS = 1; - private static final int POS_TIMESTAMP = POS_NUM_ELEMENTS + 1; - +public final class StatsEvent { private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068; - // Max payload size is 4 KB less 4 bytes which are reserved for statsEventTag. + // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag. // See android_util_StatsLog.cpp. - private static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4; - - private static final byte INT_TYPE = 0; - private static final byte LONG_TYPE = 1; - private static final byte STRING_TYPE = 2; - private static final byte LIST_TYPE = 3; - private static final byte FLOAT_TYPE = 4; - - private static final int INT_TYPE_SIZE = 5; - private static final int FLOAT_TYPE_SIZE = 5; - private static final int LONG_TYPE_SIZE = 9; - - private static final int STRING_TYPE_OVERHEAD = 5; - private static final int LIST_TYPE_OVERHEAD = 2; - - public static final int SUCCESS = 0; - public static final int ERROR_BUFFER_LIMIT_EXCEEDED = -1; - public static final int ERROR_NO_TIMESTAMP = -2; - public static final int ERROR_TIMESTAMP_ALREADY_WRITTEN = -3; - public static final int ERROR_NO_ATOM_ID = -4; - public static final int ERROR_ATOM_ID_ALREADY_WRITTEN = -5; - public static final int ERROR_UID_TAG_COUNT_MISMATCH = -6; - - private static Object sLock = new Object(); - - @GuardedBy("sLock") - private static StatsEvent sPool; - - private final byte[] mBuffer = new byte[MAX_EVENT_PAYLOAD]; - private int mPos; - private int mNumElements; - private int mAtomId; - - private StatsEvent() { - // Write LIST_TYPE to buffer - mBuffer[0] = LIST_TYPE; - reset(); - } + private static final int MAX_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4; - private void reset() { - // Reset state. - mPos = POS_TIMESTAMP; - mNumElements = 0; - mAtomId = 0; + private final Buffer mBuffer; + private final int mNumBytes; + + private StatsEvent(@NonNull final Buffer buffer, final int numBytes) { + mBuffer = buffer; + mNumBytes = numBytes; } /** - * Returns a StatsEvent object from the pool. + * Returns a new StatsEvent.Builder for building StatsEvent object. **/ @NonNull - public static StatsEvent obtain() { - final StatsEvent statsEvent; - synchronized (sLock) { - statsEvent = null == sPool ? new StatsEvent() : sPool; - sPool = null; - } - statsEvent.reset(); - return statsEvent; + public StatsEvent.Builder newBuilder() { + return new StatsEvent.Builder(Buffer.obtain()); } - @Override - public void close() { - synchronized (sLock) { - if (null == sPool) { - sPool = this; - } - } - } - - /** - * Writes the event timestamp to the buffer. - **/ - public int writeTimestampNs(final long timestampNs) { - if (hasTimestamp()) { - return ERROR_TIMESTAMP_ALREADY_WRITTEN; - } - return writeLong(timestampNs); + @NonNull + byte[] getBytes() { + return mBuffer.getBytes(); } - private boolean hasTimestamp() { - return mPos > POS_TIMESTAMP; + int getNumBytes() { + return mNumBytes; } - private boolean hasAtomId() { - return mAtomId != 0; + void release() { + mBuffer.release(); } /** - * Writes the atom id to the buffer. + * Builder for constructing a StatsEvent object. + * + * <p>This class defines and encapsulates the socket encoding for the buffer. + * The write methods must be called in the same order as the order of fields in the + * atom definition.</p> + * + * <p>setAtomId() can be called anytime before build().</p> + * + * <p>Example:</p> + * <pre> + * // Atom definition. + * message MyAtom { + * optional int32 field1 = 1; + * optional int64 field2 = 2; + * optional string field3 = 3 [(annotation1) = true]; + * } + * + * // StatsEvent construction. + * StatsEvent.newBuilder() + * StatsEvent statsEvent = StatsEvent.newBuilder() + * .setAtomId(atomId) + * .writeInt(3) // field1 + * .writeLong(8L) // field2 + * .writeString("foo") // field 3 + * .addBooleanAnnotation(annotation1Id, true) + * .build(); + * </pre> + * @hide **/ - public int writeAtomId(final int atomId) { - if (!hasTimestamp()) { - return ERROR_NO_TIMESTAMP; - } else if (hasAtomId()) { - return ERROR_ATOM_ID_ALREADY_WRITTEN; + public static final class Builder { + // Type Ids. + private static final byte TYPE_INT = 0x00; + private static final byte TYPE_LONG = 0x01; + private static final byte TYPE_STRING = 0x02; + private static final byte TYPE_LIST = 0x03; + private static final byte TYPE_FLOAT = 0x04; + private static final byte TYPE_BOOLEAN = 0x05; + private static final byte TYPE_OBJECT = 0x06; + private static final byte TYPE_BYTE_ARRAY = 0x07; + private static final byte TYPE_ATTRIBUTION_CHAIN = 0x08; + private static final byte TYPE_ERRORS = 0x0F; + + // Error flags. + private static final int ERROR_NO_TIMESTAMP = 0x1; + private static final int ERROR_NO_ATOM_ID = 0x2; + private static final int ERROR_OVERFLOW = 0x4; + private static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8; + private static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x10; + private static final int ERROR_INVALID_ANNOTATION_ID = 0x20; + private static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x40; + private static final int ERROR_TOO_MANY_ANNOTATIONS = 0x80; + private static final int ERROR_TOO_MANY_FIELDS = 0x100; + private static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x200; + + // Size limits. + private static final int MAX_ANNOTATION_COUNT = 15; + private static final int MAX_ATTRIBUTION_NODES = 127; + private static final int MAX_NUM_ELEMENTS = 127; + + // Fixed positions. + private static final int POS_NUM_ELEMENTS = 1; + private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES; + private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES; + + private final Buffer mBuffer; + private long mTimestampNs; + private int mAtomId; + private byte mCurrentAnnotationCount; + private int mPos; + private int mPosLastField; + private byte mLastType; + private int mNumElements; + private int mErrorMask; + + private Builder(final Buffer buffer) { + mBuffer = buffer; + mCurrentAnnotationCount = 0; + mAtomId = 0; + mTimestampNs = SystemClock.elapsedRealtimeNanos(); + mNumElements = 0; + + // Set mPos to 0 for writing TYPE_OBJECT at 0th position. + mPos = 0; + writeTypeId(TYPE_OBJECT); + + // Set mPos to after atom id's location in the buffer. + // First 2 elements in the buffer are event timestamp followed by the atom id. + mPos = POS_ATOM_ID + Byte.BYTES + Integer.BYTES; + mPosLastField = 0; + mLastType = 0; } - final int writeResult = writeInt(atomId); - if (SUCCESS == writeResult) { + /** + * Sets the atom id for this StatsEvent. + **/ + @NonNull + public Builder setAtomId(final int atomId) { mAtomId = atomId; + return this; } - return writeResult; - } - /** - * Appends the given int to the StatsEvent buffer. - **/ - public int writeInt(final int value) { - if (!hasTimestamp()) { - return ERROR_NO_TIMESTAMP; - } else if (!hasAtomId()) { - return ERROR_NO_ATOM_ID; - } else if (mPos + INT_TYPE_SIZE > MAX_EVENT_PAYLOAD) { - return ERROR_BUFFER_LIMIT_EXCEEDED; + /** + * Sets the timestamp in nanos for this StatsEvent. + **/ + @VisibleForTesting + @NonNull + public Builder setTimestampNs(final long timestampNs) { + mTimestampNs = timestampNs; + return this; } - mBuffer[mPos] = INT_TYPE; - copyInt(mBuffer, mPos + 1, value); - mPos += INT_TYPE_SIZE; - mNumElements++; - return SUCCESS; - } + /** + * Write a boolean field to this StatsEvent. + **/ + @NonNull + public Builder writeBoolean(final boolean value) { + // Write boolean typeId byte followed by boolean byte representation. + writeTypeId(TYPE_BOOLEAN); + mPos += mBuffer.putBoolean(mPos, value); + mNumElements++; + return this; + } - /** - * Appends the given long to the StatsEvent buffer. - **/ - public int writeLong(final long value) { - if (!hasTimestamp()) { - return ERROR_NO_TIMESTAMP; - } else if (!hasAtomId()) { - return ERROR_NO_ATOM_ID; - } else if (mPos + LONG_TYPE_SIZE > MAX_EVENT_PAYLOAD) { - return ERROR_BUFFER_LIMIT_EXCEEDED; + /** + * Write an integer field to this StatsEvent. + **/ + @NonNull + public Builder writeInt(final int value) { + // Write integer typeId byte followed by 4-byte representation of value. + writeTypeId(TYPE_INT); + mPos += mBuffer.putInt(mPos, value); + mNumElements++; + return this; } - mBuffer[mPos] = LONG_TYPE; - copyLong(mBuffer, mPos + 1, value); - mPos += LONG_TYPE_SIZE; - mNumElements++; - return SUCCESS; - } + /** + * Write a long field to this StatsEvent. + **/ + @NonNull + public Builder writeLong(final long value) { + // Write long typeId byte followed by 8-byte representation of value. + writeTypeId(TYPE_LONG); + mPos += mBuffer.putLong(mPos, value); + mNumElements++; + return this; + } - /** - * Appends the given float to the StatsEvent buffer. - **/ - public int writeFloat(final float value) { - if (!hasTimestamp()) { - return ERROR_NO_TIMESTAMP; - } else if (!hasAtomId()) { - return ERROR_NO_ATOM_ID; - } else if (mPos + FLOAT_TYPE_SIZE > MAX_EVENT_PAYLOAD) { - return ERROR_BUFFER_LIMIT_EXCEEDED; + /** + * Write a float field to this StatsEvent. + **/ + @NonNull + public Builder writeFloat(final float value) { + // Write float typeId byte followed by 4-byte representation of value. + writeTypeId(TYPE_FLOAT); + mPos += mBuffer.putFloat(mPos, value); + mNumElements++; + return this; } - mBuffer[mPos] = FLOAT_TYPE; - copyInt(mBuffer, mPos + 1, Float.floatToIntBits(value)); - mPos += FLOAT_TYPE_SIZE; - mNumElements++; - return SUCCESS; - } + /** + * Write a String field to this StatsEvent. + **/ + @NonNull + public Builder writeString(@NonNull final String value) { + // Write String typeId byte, followed by 4-byte representation of number of bytes + // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value. + final byte[] valueBytes = stringToBytes(value); + writeByteArray(valueBytes, TYPE_STRING); + return this; + } - /** - * Appends the given boolean to the StatsEvent buffer. - **/ - public int writeBoolean(final boolean value) { - return writeInt(value ? 1 : 0); - } + /** + * Write a byte array field to this StatsEvent. + **/ + @NonNull + public Builder writeByteArray(@NonNull final byte[] value) { + // Write byte array typeId byte, followed by 4-byte representation of number of bytes + // in value, followed by the actual byte array. + writeByteArray(value, TYPE_BYTE_ARRAY); + return this; + } - /** - * Appends the given byte array to the StatsEvent buffer. - **/ - public int writeByteArray(@NonNull final byte[] value) { - if (!hasTimestamp()) { - return ERROR_NO_TIMESTAMP; - } else if (!hasAtomId()) { - return ERROR_NO_ATOM_ID; - } else if (mPos + STRING_TYPE_OVERHEAD + value.length > MAX_EVENT_PAYLOAD) { - return ERROR_BUFFER_LIMIT_EXCEEDED; + private void writeByteArray(@NonNull final byte[] value, final byte typeId) { + writeTypeId(typeId); + final int numBytes = value.length; + mPos += mBuffer.putInt(mPos, numBytes); + mPos += mBuffer.putByteArray(mPos, value); + mNumElements++; } - mBuffer[mPos] = STRING_TYPE; - copyInt(mBuffer, mPos + 1, value.length); - System.arraycopy(value, 0, mBuffer, mPos + STRING_TYPE_OVERHEAD, value.length); - mPos += STRING_TYPE_OVERHEAD + value.length; - mNumElements++; - return SUCCESS; - } + /** + * Write an attribution chain field to this StatsEvent. + * + * The sizes of uids and tags must be equal. The AttributionNode at position i is + * made up of uids[i] and tags[i]. + * + * @param uids array of uids in the attribution nodes. + * @param tags array of tags in the attribution nodes. + **/ + @NonNull + public Builder writeAttributionNode( + @NonNull final int[] uids, @NonNull final String[] tags) { + final byte numUids = (byte) uids.length; + final byte numTags = (byte) tags.length; + + if (numUids != numTags) { + mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL; + } else if (numUids > MAX_ATTRIBUTION_NODES) { + mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG; + } else { + // Write attribution chain typeId byte, followed by 1-byte representation of + // number of attribution nodes, followed by encoding of each attribution node. + writeTypeId(TYPE_ATTRIBUTION_CHAIN); + mPos += mBuffer.putByte(mPos, numUids); + for (int i = 0; i < numUids; i++) { + // Each uid is encoded as 4-byte representation of its int value. + mPos += mBuffer.putInt(mPos, uids[i]); + + // Each tag is encoded as 4-byte representation of number of bytes in its + // UTF-8 encoding, followed by the actual UTF-8 bytes. + final byte[] tagBytes = stringToBytes(tags[i]); + mPos += mBuffer.putInt(mPos, tagBytes.length); + mPos += mBuffer.putByteArray(mPos, tagBytes); + } + mNumElements++; + } + return this; + } - /** - * Appends the given String to the StatsEvent buffer. - **/ - public int writeString(@NonNull final String value) { - final byte[] valueBytes = stringToBytes(value); - return writeByteArray(valueBytes); + /** + * Write a boolean annotation for the last field written. + **/ + @NonNull + public Builder addBooleanAnnotation( + final byte annotationId, final boolean value) { + // Ensure there's a field written to annotate. + if (0 == mPosLastField) { + mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; + } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { + mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; + } else { + mPos += mBuffer.putByte(mPos, annotationId); + mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN); + mPos += mBuffer.putBoolean(mPos, value); + mCurrentAnnotationCount++; + writeAnnotationCount(); + } + return this; + } + + /** + * Write an integer annotation for the last field written. + **/ + @NonNull + public Builder addIntAnnotation(final byte annotationId, final int value) { + if (0 == mPosLastField) { + mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; + } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { + mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; + } else { + mPos += mBuffer.putByte(mPos, annotationId); + mPos += mBuffer.putByte(mPos, TYPE_INT); + mPos += mBuffer.putInt(mPos, value); + mCurrentAnnotationCount++; + writeAnnotationCount(); + } + return this; + } + + /** + * Builds a StatsEvent object with values entered in this Builder. + **/ + @NonNull + public StatsEvent build() { + if (0L == mTimestampNs) { + mErrorMask |= ERROR_NO_TIMESTAMP; + } + if (0 == mAtomId) { + mErrorMask |= ERROR_NO_ATOM_ID; + } + if (mBuffer.hasOverflowed()) { + mErrorMask |= ERROR_OVERFLOW; + } + if (mNumElements > MAX_NUM_ELEMENTS) { + mErrorMask |= ERROR_TOO_MANY_FIELDS; + } + + int size = mPos; + mPos = POS_TIMESTAMP_NS; + writeLong(mTimestampNs); + writeInt(mAtomId); + if (0 == mErrorMask) { + mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements); + } else { + mBuffer.putByte(0, TYPE_ERRORS); + mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3); + mPos += mBuffer.putInt(mPos, mErrorMask); + size = mPos; + } + + return new StatsEvent(mBuffer, size); + } + + private void writeTypeId(final byte typeId) { + mPosLastField = mPos; + mLastType = typeId; + mCurrentAnnotationCount = 0; + final byte encodedId = (byte) (typeId & 0x0F); + mPos += mBuffer.putByte(mPos, encodedId); + } + + private void writeAnnotationCount() { + // Use first 4 bits for annotation count and last 4 bits for typeId. + final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F)); + mBuffer.putByte(mPosLastField, encodedId); + } + + @NonNull + private static byte[] stringToBytes(@Nullable final String value) { + return (null == value ? "" : value).getBytes(UTF_8); + } } - /** - * Appends the AttributionNode specified as array of uids and array of tags. - **/ - public int writeAttributionNode(@NonNull final int[] uids, @NonNull final String[] tags) { - if (!hasTimestamp()) { - return ERROR_NO_TIMESTAMP; - } else if (!hasAtomId()) { - return ERROR_NO_ATOM_ID; - } else if (mPos + LIST_TYPE_OVERHEAD > MAX_EVENT_PAYLOAD) { - return ERROR_BUFFER_LIMIT_EXCEEDED; + private static final class Buffer { + private static Object sLock = new Object(); + + @GuardedBy("sLock") + private static Buffer sPool; + + private final byte[] mBytes = new byte[MAX_PAYLOAD_SIZE]; + private boolean mOverflow = false; + + @NonNull + private static Buffer obtain() { + final Buffer buffer; + synchronized (sLock) { + buffer = null == sPool ? new Buffer() : sPool; + sPool = null; + } + buffer.reset(); + return buffer; } - final int numTags = tags.length; - final int numUids = uids.length; - if (numTags != numUids) { - return ERROR_UID_TAG_COUNT_MISMATCH; + private Buffer() { } - int pos = mPos; - mBuffer[pos] = LIST_TYPE; - mBuffer[pos + 1] = (byte) numTags; - pos += LIST_TYPE_OVERHEAD; - for (int i = 0; i < numTags; i++) { - final byte[] tagBytes = stringToBytes(tags[i]); + @NonNull + private byte[] getBytes() { + return mBytes; + } - if (pos + LIST_TYPE_OVERHEAD + INT_TYPE_SIZE - + STRING_TYPE_OVERHEAD + tagBytes.length > MAX_EVENT_PAYLOAD) { - return ERROR_BUFFER_LIMIT_EXCEEDED; + private void release() { + synchronized (sLock) { + if (null == sPool) { + sPool = this; + } } + } - mBuffer[pos] = LIST_TYPE; - mBuffer[pos + 1] = 2; - pos += LIST_TYPE_OVERHEAD; - mBuffer[pos] = INT_TYPE; - copyInt(mBuffer, pos + 1, uids[i]); - pos += INT_TYPE_SIZE; - mBuffer[pos] = STRING_TYPE; - copyInt(mBuffer, pos + 1, tagBytes.length); - System.arraycopy(tagBytes, 0, mBuffer, pos + STRING_TYPE_OVERHEAD, tagBytes.length); - pos += STRING_TYPE_OVERHEAD + tagBytes.length; + private void reset() { + mOverflow = false; } - mPos = pos; - mNumElements++; - return SUCCESS; - } - /** - * Returns the byte array containing data in the statsd socket format. - * @hide - **/ - @NonNull - public byte[] getBuffer() { - // Encode number of elements in the buffer. - mBuffer[POS_NUM_ELEMENTS] = (byte) mNumElements; - return mBuffer; - } + private boolean hasOverflowed() { + return mOverflow; + } - /** - * Returns number of bytes used by the buffer. - * @hide - **/ - public int size() { - return mPos; - } + /** + * Checks for available space in the byte array. + * + * @param index starting position in the buffer to start the check. + * @param numBytes number of bytes to check from index. + * @return true if space is available, false otherwise. + **/ + private boolean hasEnoughSpace(final int index, final int numBytes) { + final boolean result = index + numBytes < MAX_PAYLOAD_SIZE; + if (!result) { + mOverflow = true; + } + return result; + } - /** - * Getter for atom id. - * @hide - **/ - public int getAtomId() { - return mAtomId; - } + /** + * Writes a byte into the buffer. + * + * @param index position in the buffer where the byte is written. + * @param value the byte to write. + * @return number of bytes written to buffer from this write operation. + **/ + private int putByte(final int index, final byte value) { + if (hasEnoughSpace(index, Byte.BYTES)) { + mBytes[index] = (byte) (value); + return Byte.BYTES; + } + return 0; + } - @NonNull - private static byte[] stringToBytes(@Nullable final String value) { - return (null == value ? "" : value).getBytes(UTF_8); - } + /** + * Writes a boolean into the buffer. + * + * @param index position in the buffer where the boolean is written. + * @param value the boolean to write. + * @return number of bytes written to buffer from this write operation. + **/ + private int putBoolean(final int index, final boolean value) { + return putByte(index, (byte) (value ? 1 : 0)); + } - // Helper methods for copying primitives - private static void copyInt(@NonNull byte[] buff, int pos, int value) { - buff[pos] = (byte) (value); - buff[pos + 1] = (byte) (value >> 8); - buff[pos + 2] = (byte) (value >> 16); - buff[pos + 3] = (byte) (value >> 24); - } + /** + * Writes an integer into the buffer. + * + * @param index position in the buffer where the integer is written. + * @param value the integer to write. + * @return number of bytes written to buffer from this write operation. + **/ + private int putInt(final int index, final int value) { + if (hasEnoughSpace(index, Integer.BYTES)) { + // Use little endian byte order. + mBytes[index] = (byte) (value); + mBytes[index + 1] = (byte) (value >> 8); + mBytes[index + 2] = (byte) (value >> 16); + mBytes[index + 3] = (byte) (value >> 24); + return Integer.BYTES; + } + return 0; + } + + /** + * Writes a long into the buffer. + * + * @param index position in the buffer where the long is written. + * @param value the long to write. + * @return number of bytes written to buffer from this write operation. + **/ + private int putLong(final int index, final long value) { + if (hasEnoughSpace(index, Long.BYTES)) { + // Use little endian byte order. + mBytes[index] = (byte) (value); + mBytes[index + 1] = (byte) (value >> 8); + mBytes[index + 2] = (byte) (value >> 16); + mBytes[index + 3] = (byte) (value >> 24); + mBytes[index + 4] = (byte) (value >> 32); + mBytes[index + 5] = (byte) (value >> 40); + mBytes[index + 6] = (byte) (value >> 48); + mBytes[index + 7] = (byte) (value >> 56); + return Long.BYTES; + } + return 0; + } + + /** + * Writes a float into the buffer. + * + * @param index position in the buffer where the float is written. + * @param value the float to write. + * @return number of bytes written to buffer from this write operation. + **/ + private int putFloat(final int index, final float value) { + return putInt(index, Float.floatToIntBits(value)); + } - private static void copyLong(@NonNull byte[] buff, int pos, long value) { - buff[pos] = (byte) (value); - buff[pos + 1] = (byte) (value >> 8); - buff[pos + 2] = (byte) (value >> 16); - buff[pos + 3] = (byte) (value >> 24); - buff[pos + 4] = (byte) (value >> 32); - buff[pos + 5] = (byte) (value >> 40); - buff[pos + 6] = (byte) (value >> 48); - buff[pos + 7] = (byte) (value >> 56); + /** + * Copies a byte array into the buffer. + * + * @param index position in the buffer where the byte array is copied. + * @param value the byte array to copy. + * @return number of bytes written to buffer from this write operation. + **/ + private int putByteArray(final int index, @NonNull final byte[] value) { + final int numBytes = value.length; + if (hasEnoughSpace(index, numBytes)) { + System.arraycopy(value, 0, mBytes, index, numBytes); + return numBytes; + } + return 0; + } } } diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index ad59ae5d2bee..36daa5c57700 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -945,6 +945,94 @@ public class ViewDebug { return null; } + private static class StreamingPictureCallbackHandler implements AutoCloseable, + HardwareRenderer.PictureCapturedCallback, Runnable { + private final HardwareRenderer mRenderer; + private final Callable<OutputStream> mCallback; + private final Executor mExecutor; + private final ReentrantLock mLock = new ReentrantLock(false); + private final ArrayDeque<byte[]> mQueue = new ArrayDeque<>(3); + private final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream(); + private boolean mStopListening; + private Thread mRenderThread; + + private StreamingPictureCallbackHandler(HardwareRenderer renderer, + Callable<OutputStream> callback, Executor executor) { + mRenderer = renderer; + mCallback = callback; + mExecutor = executor; + mRenderer.setPictureCaptureCallback(this); + } + + @Override + public void close() { + mLock.lock(); + mStopListening = true; + mLock.unlock(); + mRenderer.setPictureCaptureCallback(null); + } + + @Override + public void onPictureCaptured(Picture picture) { + mLock.lock(); + if (mStopListening) { + mLock.unlock(); + mRenderer.setPictureCaptureCallback(null); + return; + } + if (mRenderThread == null) { + mRenderThread = Thread.currentThread(); + } + boolean needsInvoke = true; + if (mQueue.size() == 3) { + mQueue.removeLast(); + needsInvoke = false; + } + picture.writeToStream(mByteStream); + mQueue.add(mByteStream.toByteArray()); + mByteStream.reset(); + mLock.unlock(); + + if (needsInvoke) { + mExecutor.execute(this); + } + } + + @Override + public void run() { + mLock.lock(); + final byte[] picture = mQueue.poll(); + final boolean isStopped = mStopListening; + mLock.unlock(); + if (Thread.currentThread() == mRenderThread) { + close(); + throw new IllegalStateException( + "ViewDebug#startRenderingCommandsCapture must be given an executor that " + + "invokes asynchronously"); + } + if (isStopped) { + return; + } + OutputStream stream = null; + try { + stream = mCallback.call(); + } catch (Exception ex) { + Log.w("ViewDebug", "Aborting rendering commands capture " + + "because callback threw exception", ex); + } + if (stream != null) { + try { + stream.write(picture); + } catch (IOException ex) { + Log.w("ViewDebug", "Aborting rendering commands capture " + + "due to IOException writing to output stream", ex); + } + } else { + close(); + } + } + } + /** * Begins capturing the entire rendering commands for the view tree referenced by the given * view. The view passed may be any View in the tree as long as it is attached. That is, @@ -990,18 +1078,7 @@ public class ViewDebug { } final HardwareRenderer renderer = attachInfo.mThreadedRenderer; if (renderer != null) { - return new PictureCallbackHandler(renderer, (picture -> { - try { - OutputStream stream = callback.call(); - if (stream != null) { - picture.writeToStream(stream); - return true; - } - } catch (Exception ex) { - // fall through - } - return false; - }), executor); + return new StreamingPictureCallbackHandler(renderer, callback, executor); } return null; } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 57ce28e5059a..27402a463d4f 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1189,6 +1189,9 @@ public class Editor { } public boolean performLongClick(boolean handled) { + if (TextView.DEBUG_CURSOR) { + logCursor("performLongClick", "handled=%s", handled); + } // Long press in empty space moves cursor and starts the insertion action mode. if (!handled && !isPositionOnText(mLastDownPositionX, mLastDownPositionY) && mInsertionControllerEnabled) { @@ -1252,6 +1255,10 @@ public class Editor { } void onFocusChanged(boolean focused, int direction) { + if (TextView.DEBUG_CURSOR) { + logCursor("onFocusChanged", "focused=%s", focused); + } + mShowCursor = SystemClock.uptimeMillis(); ensureEndedBatchEdit(); @@ -1450,12 +1457,22 @@ public class Editor { } else { mTapState = TAP_STATE_TRIPLE_CLICK; } + if (TextView.DEBUG_CURSOR) { + logCursor("updateTapState", "ACTION_DOWN: %s tap detected", + (mTapState == TAP_STATE_DOUBLE_TAP ? "double" : "triple")); + } } else { mTapState = TAP_STATE_FIRST_TAP; + if (TextView.DEBUG_CURSOR) { + logCursor("updateTapState", "ACTION_DOWN: first tap detected"); + } } } if (action == MotionEvent.ACTION_UP) { mLastTouchUpTime = SystemClock.uptimeMillis(); + if (TextView.DEBUG_CURSOR) { + logCursor("updateTapState", "ACTION_UP"); + } } } @@ -2354,6 +2371,9 @@ public class Editor { } void onTouchUpEvent(MotionEvent event) { + if (TextView.DEBUG_CURSOR) { + logCursor("onTouchUpEvent", null); + } if (getSelectionActionModeHelper().resetSelection( getTextView().getOffsetForPosition(event.getX(), event.getY()))) { return; @@ -2481,6 +2501,9 @@ public class Editor { loadCursorDrawable(); final int left = clampHorizontalPosition(mDrawableForCursor, horizontal); final int width = mDrawableForCursor.getIntrinsicWidth(); + if (TextView.DEBUG_CURSOR) { + logCursor("updateCursorPosition", "left=%s, top=%s", left, (top - mTempRect.top)); + } mDrawableForCursor.setBounds(left, top - mTempRect.top, left + width, bottom + mTempRect.bottom); } @@ -4621,6 +4644,11 @@ public class Editor { } public void show() { + if (TextView.DEBUG_CURSOR) { + logCursor(getClass().getSimpleName() + ": HandleView: show()", "offset=%s", + getCurrentCursorOffset()); + } + if (isShowing()) return; getPositionListener().addSubscriber(this, true /* local position may change */); @@ -4637,6 +4665,11 @@ public class Editor { } public void hide() { + if (TextView.DEBUG_CURSOR) { + logCursor(getClass().getSimpleName() + ": HandleView: hide()", "offset=%s", + getCurrentCursorOffset()); + } + dismiss(); getPositionListener().removeSubscriber(this); @@ -5033,6 +5066,11 @@ public class Editor { @Override public boolean onTouchEvent(MotionEvent ev) { + if (TextView.DEBUG_CURSOR) { + logCursor(this.getClass().getSimpleName() + ": HandleView: onTouchEvent", + MotionEvent.actionToString(ev.getActionMasked())); + } + updateFloatingToolbarVisibility(ev); switch (ev.getActionMasked()) { @@ -5951,6 +5989,10 @@ public class Editor { distanceSquared < doubleTapSlop * doubleTapSlop; if (stayedInArea && (isMouse || isPositionOnText(eventX, eventY))) { + if (TextView.DEBUG_CURSOR) { + logCursor("SelectionModifierCursorController: onTouchEvent", + "ACTION_DOWN: select and start drag"); + } if (mTapState == TAP_STATE_DOUBLE_TAP) { selectCurrentWordAndStartDrag(); } else if (mTapState == TAP_STATE_TRIPLE_CLICK) { @@ -6028,6 +6070,9 @@ public class Editor { break; case MotionEvent.ACTION_UP: + if (TextView.DEBUG_CURSOR) { + logCursor("SelectionModifierCursorController: onTouchEvent", "ACTION_UP"); + } if (!isDragAcceleratorActive()) { break; } @@ -7119,4 +7164,12 @@ public class Editor { return resolveInfo.loadLabel(mPackageManager); } } + + private static void logCursor(String location, @Nullable String msgFormat, Object ... msgArgs) { + if (msgFormat == null) { + Log.d(TAG, location); + } else { + Log.d(TAG, location + ": " + String.format(msgFormat, msgArgs)); + } + } } diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index 562cc4ffeeaa..217693eed686 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -28,6 +28,7 @@ import android.graphics.Paint.Style; import android.graphics.Rect; import android.graphics.Typeface; import android.icu.text.DisplayContext; +import android.icu.text.RelativeDateTimeFormatter; import android.icu.text.SimpleDateFormat; import android.icu.util.Calendar; import android.os.Bundle; @@ -1095,6 +1096,14 @@ class SimpleMonthView extends View { node.setText(getDayText(virtualViewId)); node.setContentDescription(getDayDescription(virtualViewId)); + if (virtualViewId == mToday) { + RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance(); + node.setStateDescription(fmt.format(RelativeDateTimeFormatter.Direction.THIS, + RelativeDateTimeFormatter.AbsoluteUnit.DAY)); + } + if (virtualViewId == mActivatedDay) { + node.setSelected(true); + } node.setBoundsInParent(mTempRect); final boolean isDayEnabled = isDayEnabled(virtualViewId); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 31f50555af1d..90e8ef2c6423 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -345,6 +345,8 @@ import java.util.function.Supplier; public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { static final String LOG_TAG = "TextView"; static final boolean DEBUG_EXTRACT = false; + static final boolean DEBUG_CURSOR = false; + private static final float[] TEMP_POSITION = new float[2]; // Enum for the "typeface" XML parameter. @@ -10857,6 +10859,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean onTouchEvent(MotionEvent event) { + if (DEBUG_CURSOR) { + logCursor("onTouchEvent", MotionEvent.actionToString(event.getActionMasked())); + } + final int action = event.getActionMasked(); if (mEditor != null) { mEditor.onTouchEvent(event); @@ -10868,6 +10874,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } final boolean superResult = super.onTouchEvent(event); + if (DEBUG_CURSOR) { + logCursor("onTouchEvent", "superResult=%s", superResult); + } /* * Don't handle the release after a long press, because it will move the selection away from @@ -10876,7 +10885,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ if (mEditor != null && mEditor.mDiscardNextActionUp && action == MotionEvent.ACTION_UP) { mEditor.mDiscardNextActionUp = false; - + if (DEBUG_CURSOR) { + logCursor("onTouchEvent", "release after long press detected"); + } if (mEditor.mIsInsertionActionModeStartPending) { mEditor.startInsertionActionMode(); mEditor.mIsInsertionActionModeStartPending = false; @@ -12254,6 +12265,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean performLongClick() { + if (DEBUG_CURSOR) { + logCursor("performLongClick", null); + } + boolean handled = false; boolean performedHapticFeedback = false; @@ -13481,4 +13496,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener TextView.this.spanChange(buf, what, s, -1, e, -1); } } + + private static void logCursor(String location, @Nullable String msgFormat, Object ... msgArgs) { + if (msgFormat == null) { + Log.d(LOG_TAG, location); + } else { + Log.d(LOG_TAG, location + ": " + String.format(msgFormat, msgArgs)); + } + } } diff --git a/core/java/com/android/internal/app/DumpHeapActivity.java b/core/java/com/android/internal/app/DumpHeapActivity.java deleted file mode 100644 index e04e870a8ec5..000000000000 --- a/core/java/com/android/internal/app/DumpHeapActivity.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.app; - -import android.app.Activity; -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.ClipData; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.util.DebugUtils; -import android.util.Slog; - -/** - * This activity is displayed when the system has collected a heap dump from - * a large process and the user has selected to share it. - */ -public class DumpHeapActivity extends Activity { - /** The process we are reporting */ - public static final String KEY_PROCESS = "process"; - /** The size limit the process reached */ - public static final String KEY_SIZE = "size"; - /** Whether the user initiated the dump or not. */ - public static final String KEY_IS_USER_INITIATED = "is_user_initiated"; - /** Whether the process is a system process (eg: Android System) or not. */ - public static final String KEY_IS_SYSTEM_PROCESS = "is_system_process"; - /** Optional name of package to directly launch */ - public static final String KEY_DIRECT_LAUNCH = "direct_launch"; - - // Broadcast action to determine when to delete the current dump heap data. - public static final String ACTION_DELETE_DUMPHEAP = "com.android.server.am.DELETE_DUMPHEAP"; - - // Extra for above: delay delete of data, since the user is in the process of sharing it. - public static final String EXTRA_DELAY_DELETE = "delay_delete"; - - static final public Uri JAVA_URI = Uri.parse("content://com.android.server.heapdump/java"); - - String mProcess; - long mSize; - AlertDialog mDialog; - boolean mHandled = false; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mProcess = getIntent().getStringExtra(KEY_PROCESS); - mSize = getIntent().getLongExtra(KEY_SIZE, 0); - final boolean isUserInitiated = getIntent().getBooleanExtra(KEY_IS_USER_INITIATED, false); - final boolean isSystemProcess = getIntent().getBooleanExtra(KEY_IS_SYSTEM_PROCESS, false); - - String directLaunch = getIntent().getStringExtra(KEY_DIRECT_LAUNCH); - if (directLaunch != null) { - Intent intent = new Intent(ActivityManager.ACTION_REPORT_HEAP_LIMIT); - intent.setPackage(directLaunch); - ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", JAVA_URI); - intent.setClipData(clip); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setType(clip.getDescription().getMimeType(0)); - intent.putExtra(Intent.EXTRA_STREAM, JAVA_URI); - try { - startActivity(intent); - scheduleDelete(); - mHandled = true; - finish(); - return; - } catch (ActivityNotFoundException e) { - Slog.i("DumpHeapActivity", "Unable to direct launch to " + directLaunch - + ": " + e.getMessage()); - } - } - - final int messageId; - if (isUserInitiated) { - messageId = com.android.internal.R.string.dump_heap_ready_text; - } else if (isSystemProcess) { - messageId = com.android.internal.R.string.dump_heap_system_text; - } else { - messageId = com.android.internal.R.string.dump_heap_text; - } - AlertDialog.Builder b = new AlertDialog.Builder(this, - android.R.style.Theme_Material_Light_Dialog_Alert); - b.setTitle(com.android.internal.R.string.dump_heap_title); - b.setMessage(getString( - messageId, mProcess, DebugUtils.sizeValueToString(mSize, null))); - b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mHandled = true; - sendBroadcast(new Intent(ACTION_DELETE_DUMPHEAP)); - finish(); - } - }); - b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mHandled = true; - scheduleDelete(); - Intent intent = new Intent(Intent.ACTION_SEND); - ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", JAVA_URI); - intent.setClipData(clip); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setType(clip.getDescription().getMimeType(0)); - intent.putExtra(Intent.EXTRA_STREAM, JAVA_URI); - startActivity(Intent.createChooser(intent, - getText(com.android.internal.R.string.dump_heap_title))); - finish(); - } - }); - mDialog = b.show(); - } - - void scheduleDelete() { - Intent broadcast = new Intent(ACTION_DELETE_DUMPHEAP); - broadcast.putExtra(EXTRA_DELAY_DELETE, true); - sendBroadcast(broadcast); - } - - @Override - protected void onStop() { - super.onStop(); - if (!isChangingConfigurations()) { - if (!mHandled) { - sendBroadcast(new Intent(ACTION_DELETE_DUMPHEAP)); - } - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mDialog.dismiss(); - } -} diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java index 2f9136a2577e..392b8d300397 100644 --- a/core/java/com/android/internal/app/procstats/ProcessState.java +++ b/core/java/com/android/internal/app/procstats/ProcessState.java @@ -77,7 +77,6 @@ public final class ProcessState { STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI STATE_TOP, // ActivityManager.PROCESS_STATE_TOP - STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java index fd2ada08edc1..36bc22906695 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java @@ -49,6 +49,18 @@ public final class CompatibilityChangeConfig implements Parcelable { return mChangeConfig.forceDisabledSet(); } + /** + * Returns if a change is enabled or disabled in this config. + */ + public boolean isChangeEnabled(long changeId) { + if (mChangeConfig.isForceEnabled(changeId)) { + return true; + } else if (mChangeConfig.isForceDisabled(changeId)) { + return false; + } + throw new IllegalStateException("Change " + changeId + " is not defined."); + } + private CompatibilityChangeConfig(Parcel in) { long[] enabledArray = in.createLongArray(); long[] disabledArray = in.createLongArray(); diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl new file mode 100644 index 000000000000..3bc72771f99c --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.compat; + +parcelable CompatibilityChangeInfo; diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java new file mode 100644 index 000000000000..e48e2df4043c --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.compat; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class is a parcelable version of {@link com.android.server.compat.Change}. + * + * @hide + */ +public class CompatibilityChangeInfo implements Parcelable { + private final long mChangeId; + private final @Nullable String mName; + private final int mEnableAfterTargetSdk; + private final boolean mDisabled; + + public long getId() { + return mChangeId; + } + + @Nullable + public String getName() { + return mName; + } + + public int getEnableAfterTargetSdk() { + return mEnableAfterTargetSdk; + } + + public boolean getDisabled() { + return mDisabled; + } + + public CompatibilityChangeInfo( + Long changeId, String name, int enableAfterTargetSdk, boolean disabled) { + this.mChangeId = changeId; + this.mName = name; + this.mEnableAfterTargetSdk = enableAfterTargetSdk; + this.mDisabled = disabled; + } + + private CompatibilityChangeInfo(Parcel in) { + mChangeId = in.readLong(); + mName = in.readString(); + mEnableAfterTargetSdk = in.readInt(); + mDisabled = in.readBoolean(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mChangeId); + dest.writeString(mName); + dest.writeInt(mEnableAfterTargetSdk); + dest.writeBoolean(mDisabled); + } + + public static final Parcelable.Creator<CompatibilityChangeInfo> CREATOR = + new Parcelable.Creator<CompatibilityChangeInfo>() { + + @Override + public CompatibilityChangeInfo createFromParcel(Parcel in) { + return new CompatibilityChangeInfo(in); + } + + @Override + public CompatibilityChangeInfo[] newArray(int size) { + return new CompatibilityChangeInfo[size]; + } + }; +} diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index 8391ad2f12c2..5857642cbd4e 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -17,8 +17,10 @@ package com.android.internal.compat; import android.content.pm.ApplicationInfo; +import java.util.Map; parcelable CompatibilityChangeConfig; +parcelable CompatibilityChangeInfo; /** * Platform private API for talking with the PlatformCompat service. @@ -146,4 +148,21 @@ interface IPlatformCompat * */ void clearOverrides(in String packageName); + + /** + * Get configs for an application. + * + * @param appInfo The application whose config will be returned. + * + * @return A {@link CompatibilityChangeConfig}, representing whether a change is enabled for + * the given app or not. + */ + CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo); + + /** + * List all compatibility changes. + * + * @return An array of {@link CompatChangeInfo} known to the service. + */ + CompatibilityChangeInfo[] listAllChanges(); } diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp index 03fcdef8fbfe..1d085e5ccc49 100644 --- a/core/jni/android_graphics_Picture.cpp +++ b/core/jni/android_graphics_Picture.cpp @@ -20,9 +20,12 @@ #include "SkCanvas.h" #include "SkStream.h" #include "core_jni_helpers.h" +#include "nativehelper/jni_macros.h" #include <jni.h> +#include <array> + namespace android { static jlong android_graphics_Picture_newPicture(JNIEnv* env, jobject, jlong srcHandle) { @@ -91,20 +94,20 @@ static void android_graphics_Picture_endRecording(JNIEnv* env, jobject, jlong pi pict->endRecording(); } -static const JNINativeMethod gMethods[] = { - {"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth}, - {"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight}, - {"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture}, - {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)android_graphics_Picture_deserialize}, - {"nativeBeginRecording", "(JII)J", (void*) android_graphics_Picture_beginRecording}, - {"nativeEndRecording", "(J)V", (void*) android_graphics_Picture_endRecording}, - {"nativeDraw", "(JJ)V", (void*) android_graphics_Picture_draw}, - {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)android_graphics_Picture_serialize}, - {"nativeDestructor","(J)V", (void*) android_graphics_Picture_killPicture} +static const std::array gMethods = { + MAKE_JNI_NATIVE_METHOD("nativeGetWidth", "(J)I", android_graphics_Picture_getWidth), + MAKE_JNI_NATIVE_METHOD("nativeGetHeight", "(J)I", android_graphics_Picture_getHeight), + MAKE_JNI_NATIVE_METHOD("nativeConstructor", "(J)J", android_graphics_Picture_newPicture), + MAKE_JNI_NATIVE_METHOD("nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", android_graphics_Picture_deserialize), + MAKE_JNI_NATIVE_METHOD("nativeBeginRecording", "(JII)J", android_graphics_Picture_beginRecording), + MAKE_JNI_NATIVE_METHOD("nativeEndRecording", "(J)V", android_graphics_Picture_endRecording), + MAKE_JNI_NATIVE_METHOD("nativeDraw", "(JJ)V", android_graphics_Picture_draw), + MAKE_JNI_NATIVE_METHOD("nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", android_graphics_Picture_serialize), + MAKE_JNI_NATIVE_METHOD("nativeDestructor","(J)V", android_graphics_Picture_killPicture) }; int register_android_graphics_Picture(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/graphics/Picture", gMethods, NELEM(gMethods)); + return RegisterMethodsOrDie(env, "android/graphics/Picture", gMethods.data(), gMethods.size()); } }; // namespace android diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index d01a45c2002a..2f87debce978 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -771,10 +771,11 @@ message ActivityManagerServiceDumpProcessesProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; optional string proc_name = 1; - optional string file = 2 [ (.android.privacy).dest = DEST_EXPLICIT ]; + reserved 2; // file, DEST_EXPLICIT optional int32 pid = 3; optional int32 uid = 4; optional bool is_user_initiated = 5; + optional string uri = 6 [ (.android.privacy).dest = DEST_EXPLICIT ]; } optional Dump dump = 2; } diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index a346a63841fe..69e67d154d27 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -231,7 +231,7 @@ message AppWindowTokenProto { optional WindowTokenProto window_token = 2; optional bool last_surface_showing = 3; optional bool is_waiting_for_transition_start = 4; - optional bool is_really_animating = 5; + optional bool is_animating = 5; optional AppWindowThumbnailProto thumbnail = 6; optional bool fills_parent = 7; optional bool app_stopped = 8; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5bb18015c879..a15e1aea7a82 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -497,6 +497,7 @@ <protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" /> <protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" /> <protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" /> + <protected-broadcast android:name="android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED" /> <protected-broadcast android:name="android.telephony.action.SECRET_CODE" /> <protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" /> <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" /> @@ -4735,19 +4736,6 @@ android:excludeFromRecents="true" android:process=":ui"> </activity> - <activity android:name="com.android.internal.app.DumpHeapActivity" - android:theme="@style/Theme.Translucent.NoTitleBar" - android:label="@string/dump_heap_title" - android:finishOnCloseSystemDialogs="true" - android:noHistory="true" - android:excludeFromRecents="true" - android:process=":ui"> - </activity> - <provider android:name="com.android.server.am.DumpHeapProvider" - android:authorities="com.android.server.heapdump" - android:grantUriPermissions="true" - android:multiprocess="false" - android:singleUser="true" /> <activity android:name="android.accounts.ChooseAccountActivity" android:excludeFromRecents="true" diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 342259d18b05..ecdf5373f24f 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -169,12 +169,6 @@ "group": "WM_DEBUG_RESIZE", "at": "com\/android\/server\/wm\/WindowState.java" }, - "-1822611824": { - "message": "\tRemove token=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, "-1797409732": { "message": "Skipping %s because %s", "level": "VERBOSE", @@ -421,6 +415,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-1248645819": { + "message": "\tAdd container=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + }, "-1219773477": { "message": "setInputConsumerEnabled(%s): mCanceled=%b", "level": "DEBUG", @@ -493,12 +493,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-1099052739": { - "message": "\tAdd token=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, "-1089874824": { "message": "SURFACE SHOW (performLayout): %s", "level": "INFO", @@ -721,6 +715,12 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/DisplayContent.java" }, + "-633961578": { + "message": "applyAnimation: transition animation is disabled or skipped. container=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-622997754": { "message": "postWindowRemoveCleanupLocked: %s", "level": "VERBOSE", @@ -883,12 +883,6 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-253016819": { - "message": "applyAnimation: transition animation is disabled or skipped. atoken=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "-251259736": { "message": "No longer freezing: %s", "level": "VERBOSE", @@ -961,6 +955,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/Session.java" }, + "-33096143": { + "message": "applyAnimation: transition animation is disabled or skipped. container=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" + }, "-29233992": { "message": "SURFACE CLEAR CROP: %s", "level": "INFO", @@ -1375,6 +1375,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowSurfaceController.java" }, + "638429464": { + "message": "\tRemove container=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + }, "644675193": { "message": "Real start recents", "level": "DEBUG", @@ -1465,12 +1471,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "815803557": { - "message": "applyAnimation: atoken=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "829434921": { "message": "Draw state now committed in %s", "level": "VERBOSE", @@ -1543,6 +1543,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "972354148": { + "message": "\tcontainer=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + }, "1001904964": { "message": "***** BOOT TIMEOUT: forcing display enabled", "level": "WARN", @@ -1675,12 +1681,6 @@ "group": "WM_DEBUG_FOCUS", "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "1358786604": { - "message": "No thumbnail header bitmap for: %d", - "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "1364498663": { "message": "notifyAppResumed: wasStopped=%b %s", "level": "VERBOSE", @@ -1795,11 +1795,11 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "1531527061": { - "message": "createAnimationAdapter(): token=%s", + "1528528509": { + "message": "No thumbnail header bitmap for: %s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1563755163": { "message": "Permission Denial: %s from pid=%d, uid=%d requires %s", @@ -1819,6 +1819,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/WindowState.java" }, + "1584270979": { + "message": "applyAnimation: container=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" + }, "1589610525": { "message": "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: anim=%s transit=%s isEntrance=true Callers=%s", "level": "VERBOSE", @@ -1909,11 +1915,11 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1804869745": { + "1831008694": { "message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s", "level": "DEBUG", "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/WindowContainer.java" }, "1836214582": { "message": "startingData was nulled out before handling mAddStartingWindow: %s", @@ -1939,12 +1945,6 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/DisplayPolicy.java" }, - "1865246212": { - "message": "\tapp=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, "1866772666": { "message": "SAFE MODE not enabled", "level": "INFO", @@ -2017,6 +2017,12 @@ "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "2022422429": { + "message": "createAnimationAdapter(): container=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + }, "2028163120": { "message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s", "level": "VERBOSE", diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index c6586ecfceb9..45b2de5f4b31 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -784,7 +784,9 @@ public class GradientDrawable extends Drawable { mFillPaint.setDither(st.mDither); mFillPaint.setColorFilter(colorFilter); if (colorFilter != null && st.mSolidColors == null) { - mFillPaint.setColor(mAlpha << 24); + // If we don't have a solid color and we don't have a gradient, + // the app is stroking the shape, set the color to transparent + mFillPaint.setColor(st.mGradientColors != null ? mAlpha << 24 : 0); } if (haveStroke) { mStrokePaint.setAlpha(currStrokeAlpha); diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 40bff88b7512..3681c69e912b 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -302,6 +302,7 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) { switch (skBitmap.info().colorType()) { case kRGBA_8888_SkColorType: formatInfo.isSupported = true; + [[fallthrough]]; // ARGB_4444 is upconverted to RGBA_8888 case kARGB_4444_SkColorType: formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_8888; diff --git a/location/java/android/location/ILocationListener.aidl b/location/java/android/location/ILocationListener.aidl index ec1134566b24..8479caf367b0 100644 --- a/location/java/android/location/ILocationListener.aidl +++ b/location/java/android/location/ILocationListener.aidl @@ -31,8 +31,6 @@ oneway interface ILocationListener void onProviderEnabled(String provider); @UnsupportedAppUsage void onProviderDisabled(String provider); - - // --- deprecated --- - @UnsupportedAppUsage - void onStatusChanged(String provider, int status, in Bundle extras); + // called when the listener is removed from the server side; no further callbacks are expected + void onRemoved(); } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 87b3be9cc26d..b7dd543680dc 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -708,6 +708,7 @@ public class LocationManager { * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} * instead as it does not carry a risk of extreme battery drain. */ + @Deprecated @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate( @NonNull Criteria criteria, @@ -737,6 +738,7 @@ public class LocationManager { * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} * instead as it does not carry a risk of extreme battery drain. */ + @Deprecated @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String provider, @NonNull PendingIntent pendingIntent) { @@ -765,6 +767,7 @@ public class LocationManager { * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} * instead as it does not carry a risk of extreme battery drain. */ + @Deprecated @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) { @@ -2481,9 +2484,6 @@ public class LocationManager { } @Override - public void onStatusChanged(String provider, int status, Bundle extras) {} - - @Override public void onProviderEnabled(String provider) {} @Override @@ -2493,6 +2493,11 @@ public class LocationManager { deliverResult(null); } + @Override + public void onRemoved() { + deliverResult(null); + } + private synchronized void deliverResult(@Nullable Location location) { if (mExecutor == null) { return; @@ -2568,37 +2573,6 @@ public class LocationManager { } @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - Executor currentExecutor = mExecutor; - if (currentExecutor == null) { - return; - } - - try { - currentExecutor.execute(() -> { - try { - if (currentExecutor != mExecutor) { - return; - } - - // we may be under the binder identity if a direct executor is used - long identity = Binder.clearCallingIdentity(); - try { - mListener.onStatusChanged(provider, status, extras); - } finally { - Binder.restoreCallingIdentity(identity); - } - } finally { - locationCallbackFinished(); - } - }); - } catch (RejectedExecutionException e) { - locationCallbackFinished(); - throw e; - } - } - - @Override public void onProviderEnabled(String provider) { Executor currentExecutor = mExecutor; if (currentExecutor == null) { @@ -2660,6 +2634,14 @@ public class LocationManager { } } + @Override + public void onRemoved() { + unregister(); + synchronized (mListeners) { + mListeners.remove(mListener, this); + } + } + private void locationCallbackFinished() { try { mService.locationCallbackFinished(this); @@ -2757,9 +2739,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssStatusListener(); - return mService.registerGnssStatusCallback(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId()); + GnssStatusListener transport = new GnssStatusListener(); + if (mService.registerGnssStatusCallback(transport, mContext.getPackageName(), + mContext.getFeatureId())) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2817,10 +2804,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssMeasurementsListener(); - return mService.addGnssMeasurementsListener(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId(), - "gnss measurement callback"); + GnssMeasurementsListener transport = new GnssMeasurementsListener(); + if (mService.addGnssMeasurementsListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss measurement callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2854,10 +2845,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssNavigationMessageListener(); - return mService.addGnssNavigationMessageListener(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId(), - "gnss navigation callback"); + GnssNavigationMessageListener transport = new GnssNavigationMessageListener(); + if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss navigation callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2891,9 +2886,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new BatchedLocationCallback(); - return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName(), - mContext.getFeatureId(), "batched location callback"); + BatchedLocationCallback transport = new BatchedLocationCallback(); + if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(), + mContext.getFeatureId(), "batched location callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java index f813d1b68419..7bc2b31b16fa 100644 --- a/media/java/android/media/ImageWriter.java +++ b/media/java/android/media/ImageWriter.java @@ -192,13 +192,15 @@ public class ImageWriter implements AutoCloseable { mMaxImages = maxImages; - if (format == ImageFormat.UNKNOWN) { - format = SurfaceUtils.getSurfaceFormat(surface); - } // Note that the underlying BufferQueue is working in synchronous mode // to avoid dropping any buffers. mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, format); + // nativeInit internally overrides UNKNOWN format. So does surface format query after + // nativeInit and before getEstimatedNativeAllocBytes(). + if (format == ImageFormat.UNKNOWN) { + format = SurfaceUtils.getSurfaceFormat(surface); + } // Estimate the native buffer allocation size and register it so it gets accounted for // during GC. Note that this doesn't include the buffers required by the buffer queue // itself and the buffers requested by the producer. diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index cc5ddeb49813..5d2bdd756840 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -34,6 +34,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -62,7 +63,8 @@ public class MediaMetadataRetriever implements AutoCloseable { * method before the rest of the methods in this class. This method may be * time-consuming. * - * @param path The path of the input media file. + * @param path The path, or the URI (doesn't support streaming source currently) + * of the input media file. * @throws IllegalArgumentException If the path is invalid. */ public void setDataSource(String path) throws IllegalArgumentException { @@ -70,6 +72,15 @@ public class MediaMetadataRetriever implements AutoCloseable { throw new IllegalArgumentException("null path"); } + final Uri uri = Uri.parse(path); + final String scheme = uri.getScheme(); + if ("file".equals(scheme)) { + path = uri.getPath(); + } else if (scheme != null) { + setDataSource(path, new HashMap<String, String>()); + return; + } + try (FileInputStream is = new FileInputStream(path)) { FileDescriptor fd = is.getFD(); setDataSource(fd, 0, 0x7ffffffffffffffL); diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 3742f970e8fd..2f53cbb24129 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -99,13 +99,14 @@ cc_library_shared { "android_media_Utils.cpp", ], + header_libs: [ + "libgui_headers", + ], + shared_libs: [ "liblog", - "libgui", - "libnativewindow", "libui", "libutils", - "android.hidl.token@1.0-utils", ], include_dirs: [ diff --git a/packages/CarSystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml index fb67b302a4ae..d6c16cb4180b 100644 --- a/packages/CarSystemUI/res/values/integers_car.xml +++ b/packages/CarSystemUI/res/values/integers_car.xml @@ -34,4 +34,7 @@ <!-- The delay before the unlock dialog pops up --> <integer name="unlock_dialog_delay_ms">0</integer> + <!-- Timeout values in milliseconds for displaying volume dialog--> + <integer name="car_volume_dialog_display_normal_timeout">3000</integer> + <integer name="car_volume_dialog_display_hovering_timeout">16000</integer> </resources> diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java index 4f7b5d530c96..59b1068fb7b2 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java @@ -16,19 +16,87 @@ package com.android.systemui; +import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; + +import android.content.Context; +import android.os.PowerManager; +import android.util.DisplayMetrics; + +import com.android.internal.logging.MetricsLogger; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.appops.AppOpsController; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.navigationbar.car.CarNavigationBar; +import com.android.systemui.navigationbar.car.CarNavigationBarController; import com.android.systemui.pip.PipUI; +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.power.PowerUI; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsModule; +import com.android.systemui.statusbar.FeatureFlags; +import com.android.systemui.statusbar.NavigationBarController; +import com.android.systemui.statusbar.NotificationListener; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationViewHierarchyManager; +import com.android.systemui.statusbar.PulseExpansionHandler; +import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.car.CarStatusBar; +import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.NewNotifPipeline; +import com.android.systemui.statusbar.notification.NotificationAlertingManager; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; +import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.logging.NotifLog; +import com.android.systemui.statusbar.notification.logging.NotificationLogger; +import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.phone.AutoHideController; +import com.android.systemui.statusbar.phone.BiometricUnlockController; +import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.DozeScrimController; +import com.android.systemui.statusbar.phone.DozeServiceHost; +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; +import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.LightBarController; +import com.android.systemui.statusbar.phone.LockscreenWallpaper; +import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; +import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.statusbar.phone.StatusBarWindowViewController; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; +import com.android.systemui.statusbar.policy.UserSwitcherController; +import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.util.InjectionInflationController; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.volume.VolumeUI; +import javax.inject.Named; +import javax.inject.Singleton; + import dagger.Binds; +import dagger.Lazy; import dagger.Module; +import dagger.Provides; import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; @@ -100,4 +168,141 @@ public abstract class CarSystemUIBinder { @IntoMap @ClassKey(VolumeUI.class) public abstract SystemUI bindVolumeUI(VolumeUI sysui); + + /** + * Provides our instance of StatusBar which is considered optional. + */ + @Provides + @Singleton + static CarStatusBar provideStatusBar( + Context context, + FeatureFlags featureFlags, + LightBarController lightBarController, + AutoHideController autoHideController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + StatusBarIconController statusBarIconController, + DozeLog dozeLog, + InjectionInflationController injectionInflationController, + PulseExpansionHandler pulseExpansionHandler, + NotificationWakeUpCoordinator notificationWakeUpCoordinator, + KeyguardBypassController keyguardBypassController, + KeyguardStateController keyguardStateController, + HeadsUpManagerPhone headsUpManagerPhone, + DynamicPrivacyController dynamicPrivacyController, + BypassHeadsUpNotifier bypassHeadsUpNotifier, + @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress, + Lazy<NewNotifPipeline> newNotifPipeline, + FalsingManager falsingManager, + BroadcastDispatcher broadcastDispatcher, + RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, + NotificationGutsManager notificationGutsManager, + NotificationLogger notificationLogger, + NotificationEntryManager notificationEntryManager, + NotificationInterruptionStateProvider notificationInterruptionStateProvider, + NotificationViewHierarchyManager notificationViewHierarchyManager, + ForegroundServiceController foregroundServiceController, + AppOpsController appOpsController, + KeyguardViewMediator keyguardViewMediator, + ZenModeController zenModeController, + NotificationAlertingManager notificationAlertingManager, + DisplayMetrics displayMetrics, + MetricsLogger metricsLogger, + UiOffloadThread uiOffloadThread, + NotificationMediaManager notificationMediaManager, + NotificationLockscreenUserManager lockScreenUserManager, + NotificationRemoteInputManager remoteInputManager, + UserSwitcherController userSwitcherController, + NetworkController networkController, + BatteryController batteryController, + SysuiColorExtractor colorExtractor, + ScreenLifecycle screenLifecycle, + WakefulnessLifecycle wakefulnessLifecycle, + SysuiStatusBarStateController statusBarStateController, + VibratorHelper vibratorHelper, + BubbleController bubbleController, + NotificationGroupManager groupManager, + NotificationGroupAlertTransferHelper groupAlertTransferHelper, + VisualStabilityManager visualStabilityManager, + DeviceProvisionedController deviceProvisionedController, + NavigationBarController navigationBarController, + AssistManager assistManager, + NotificationListener notificationListener, + ConfigurationController configurationController, + StatusBarWindowController statusBarWindowController, + StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder, + NotifLog notifLog, + DozeParameters dozeParameters, + ScrimController scrimController, + Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, + Lazy<BiometricUnlockController> biometricUnlockControllerLazy, + DozeServiceHost dozeServiceHost, + PowerManager powerManager, + DozeScrimController dozeScrimController, + CarNavigationBarController carNavigationBarController) { + return new CarStatusBar( + context, + featureFlags, + lightBarController, + autoHideController, + keyguardUpdateMonitor, + statusBarIconController, + dozeLog, + injectionInflationController, + pulseExpansionHandler, + notificationWakeUpCoordinator, + keyguardBypassController, + keyguardStateController, + headsUpManagerPhone, + dynamicPrivacyController, + bypassHeadsUpNotifier, + allowNotificationLongPress, + newNotifPipeline, + falsingManager, + broadcastDispatcher, + remoteInputQuickSettingsDisabler, + notificationGutsManager, + notificationLogger, + notificationEntryManager, + notificationInterruptionStateProvider, + notificationViewHierarchyManager, + foregroundServiceController, + appOpsController, + keyguardViewMediator, + zenModeController, + notificationAlertingManager, + displayMetrics, + metricsLogger, + uiOffloadThread, + notificationMediaManager, + lockScreenUserManager, + remoteInputManager, + userSwitcherController, + networkController, + batteryController, + colorExtractor, + screenLifecycle, + wakefulnessLifecycle, + statusBarStateController, + vibratorHelper, + bubbleController, + groupManager, + groupAlertTransferHelper, + visualStabilityManager, + deviceProvisionedController, + navigationBarController, + assistManager, + notificationListener, + configurationController, + statusBarWindowController, + statusBarWindowViewControllerBuilder, + notifLog, + dozeParameters, + scrimController, + lockscreenWallpaperLazy, + biometricUnlockControllerLazy, + dozeServiceHost, + powerManager, + dozeScrimController, + carNavigationBarController); + } } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index d548fa15fe1a..85472ff5ac34 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -134,16 +134,13 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Map; -import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Lazy; /** * A status bar tailored for the automotive use case. */ -@Singleton public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler { private static final String TAG = "CarStatusBar"; // used to calculate how fast to open or close the window @@ -236,7 +233,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt } }; - @Inject public CarStatusBar( Context context, FeatureFlags featureFlags, diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java index 05657fff70e0..fb1870a6ea42 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.car; import static android.content.DialogInterface.BUTTON_NEGATIVE; import static android.content.DialogInterface.BUTTON_POSITIVE; import static android.os.UserManager.DISALLOW_ADD_USER; +import static android.os.UserManager.SWITCHABILITY_STATUS_OK; import android.app.ActivityManager; import android.app.AlertDialog; @@ -123,10 +124,12 @@ public class UserGridRecyclerView extends RecyclerView { } private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) { + int fgUserId = ActivityManager.getCurrentUser(); + UserHandle fgUserHandle = UserHandle.of(fgUserId); List<UserRecord> userRecords = new ArrayList<>(); // If the foreground user CANNOT switch to other users, only display the foreground user. - if (!mCarUserManagerHelper.canForegroundUserSwitchUsers()) { + if (mUserManager.getUserSwitchability(fgUserHandle) != SWITCHABILITY_STATUS_OK) { userRecords.add(createForegroundUserRecord()); return userRecords; } @@ -137,7 +140,7 @@ public class UserGridRecyclerView extends RecyclerView { continue; } - boolean isForeground = ActivityManager.getCurrentUser() == userInfo.id; + boolean isForeground = fgUserId == userInfo.id; UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */, false /* isAddUser */, isForeground); userRecords.add(record); @@ -147,7 +150,6 @@ public class UserGridRecyclerView extends RecyclerView { userRecords.add(createStartGuestUserRecord()); // Add add user record if the foreground user can add users - UserHandle fgUserHandle = UserHandle.of(ActivityManager.getCurrentUser()); if (!mUserManager.hasUserRestriction(DISALLOW_ADD_USER, fgUserHandle)) { userRecords.add(createAddUserRecord()); } diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java index d979bad94677..09223e8ff4c3 100644 --- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java @@ -62,7 +62,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; /** @@ -76,8 +75,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { private static final String XML_TAG_VOLUME_ITEMS = "carVolumeItems"; private static final String XML_TAG_VOLUME_ITEM = "item"; - private static final int HOVERING_TIMEOUT = 16000; - private static final int NORMAL_TIMEOUT = 3000; private static final int LISTVIEW_ANIMATION_DURATION_IN_MILLIS = 250; private static final int DISMISS_DELAY_IN_MILLIS = 50; private static final int ARROW_FADE_IN_START_DELAY_IN_MILLIS = 100; @@ -91,12 +88,23 @@ public class CarVolumeDialogImpl implements VolumeDialog { // Volume items in the RecyclerView. private final List<CarVolumeItem> mCarVolumeLineItems = new ArrayList<>(); private final KeyguardManager mKeyguard; + private final int mNormalTimeout; + private final int mHoveringTimeout; + private Window mWindow; private CustomDialog mDialog; private RecyclerView mListView; private CarVolumeItemAdapter mVolumeItemsAdapter; private Car mCar; private CarAudioManager mCarAudioManager; + private boolean mHovering; + private int mCurrentlyDisplayingGroupId; + private int mPreviouslyDisplayingGroupId; + private boolean mShowing; + private boolean mDismissing; + private boolean mExpanded; + private View mExpandIcon; + private final CarAudioManager.CarVolumeCallback mVolumeChangeCallback = new CarAudioManager.CarVolumeCallback() { @Override @@ -126,6 +134,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { volumeItem.progress = value; } if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { + mPreviouslyDisplayingGroupId = mCurrentlyDisplayingGroupId; mCurrentlyDisplayingGroupId = groupId; mHandler.obtainMessage(H.SHOW, Events.SHOW_REASON_VOLUME_CHANGED).sendToTarget(); @@ -137,12 +146,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { // ignored } }; - private boolean mHovering; - private int mCurrentlyDisplayingGroupId; - private boolean mShowing; - private boolean mDismissing; - private boolean mExpanded; - private View mExpandIcon; private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> { if (!ready) { @@ -158,7 +161,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { mAvailableVolumeItems.add(volumeItem); // The first one is the default item. if (groupId == 0) { - setuptListItem(0); + clearAllAndSetupDefaultCarVolumeLineItem(0); } } @@ -169,18 +172,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback); }; - private void setuptListItem(int groupId) { - mCarVolumeLineItems.clear(); - VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); - volumeItem.defaultItem = true; - addCarVolumeListItem(volumeItem, /* volumeGroupId = */ groupId, - R.drawable.car_ic_keyboard_arrow_down, new ExpandIconListener() - ); - } - public CarVolumeDialogImpl(Context context) { mContext = context; mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + mNormalTimeout = mContext.getResources().getInteger( + R.integer.car_volume_dialog_display_normal_timeout); + mHoveringTimeout = mContext.getResources().getInteger( + R.integer.car_volume_dialog_display_hovering_timeout); } private static int getSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { @@ -204,7 +202,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { @Override public void destroy() { - mHandler.removeCallbacksAndMessages(null); + mHandler.removeCallbacksAndMessages(/* token= */ null); cleanupAudioManager(); // unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup @@ -280,19 +278,36 @@ public class CarVolumeDialogImpl implements VolumeDialog { mHandler.removeMessages(H.SHOW); mHandler.removeMessages(H.DISMISS); + rescheduleTimeoutH(); + // Refresh the data set before showing. mVolumeItemsAdapter.notifyDataSetChanged(); + if (mShowing) { + if (mPreviouslyDisplayingGroupId == mCurrentlyDisplayingGroupId || mExpanded) { + return; + } + + clearAllAndSetupDefaultCarVolumeLineItem(mCurrentlyDisplayingGroupId); return; } + mShowing = true; - setuptListItem(mCurrentlyDisplayingGroupId); + clearAllAndSetupDefaultCarVolumeLineItem(mCurrentlyDisplayingGroupId); mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); } - private void rescheduleTimeoutH() { + private void clearAllAndSetupDefaultCarVolumeLineItem(int groupId) { + mCarVolumeLineItems.clear(); + VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); + volumeItem.defaultItem = true; + addCarVolumeListItem(volumeItem, /* volumeGroupId = */ groupId, + R.drawable.car_ic_keyboard_arrow_down, new ExpandIconListener()); + } + + protected void rescheduleTimeoutH() { mHandler.removeMessages(H.DISMISS); final int timeout = computeTimeoutH(); mHandler.sendMessageDelayed(mHandler @@ -304,7 +319,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { } private int computeTimeoutH() { - return mHovering ? HOVERING_TIMEOUT : NORMAL_TIMEOUT; + return mHovering ? mHoveringTimeout : mNormalTimeout; } private void dismissH(int reason) { @@ -366,12 +381,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { if (XML_TAG_VOLUME_ITEM.equals(parser.getName())) { TypedArray item = mContext.getResources().obtainAttributes( attrs, R.styleable.carVolumeItems_item); - int usage = item.getInt(R.styleable.carVolumeItems_item_usage, -1); + int usage = item.getInt(R.styleable.carVolumeItems_item_usage, + /* defValue= */ -1); if (usage >= 0) { VolumeItem volumeItem = new VolumeItem(); volumeItem.rank = rank; - volumeItem.icon = item.getResourceId(R.styleable.carVolumeItems_item_icon, - 0); + volumeItem.icon = item.getResourceId( + R.styleable.carVolumeItems_item_icon, /* defValue= */ 0); mVolumeItems.put(usage, volumeItem); rank++; } @@ -396,22 +412,22 @@ public class CarVolumeDialogImpl implements VolumeDialog { return result; } - private CarVolumeItem addCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId, - int supplementalIconId, + private CarVolumeItem createCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId, + Drawable supplementalIcon, int seekbarProgressValue, @Nullable View.OnClickListener supplementalIconOnClickListener) { CarVolumeItem carVolumeItem = new CarVolumeItem(); carVolumeItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); - int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); - int progress = getSeekbarValue(mCarAudioManager, volumeGroupId); - carVolumeItem.setProgress(progress); + carVolumeItem.setProgress(seekbarProgressValue); carVolumeItem.setOnSeekBarChangeListener( new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager)); - Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); + carVolumeItem.setGroupId(volumeGroupId); + + int color = mContext.getColor(R.color.car_volume_dialog_tint); + Drawable primaryIcon = mContext.getDrawable(volumeItem.icon); primaryIcon.mutate().setTint(color); carVolumeItem.setPrimaryIcon(primaryIcon); - if (supplementalIconId != 0) { - Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId); + if (supplementalIcon != null) { supplementalIcon.mutate().setTint(color); carVolumeItem.setSupplementalIcon(supplementalIcon, /* showSupplementalIconDivider= */ true); @@ -420,21 +436,23 @@ public class CarVolumeDialogImpl implements VolumeDialog { carVolumeItem.setSupplementalIcon(/* drawable= */ null, /* showSupplementalIconDivider= */ false); } - carVolumeItem.setGroupId(volumeGroupId); - mCarVolumeLineItems.add(carVolumeItem); + volumeItem.carVolumeItem = carVolumeItem; - volumeItem.progress = progress; + volumeItem.progress = seekbarProgressValue; + return carVolumeItem; } - private VolumeItem findVolumeItem(CarVolumeItem targetItem) { - for (int i = 0; i < mVolumeItems.size(); ++i) { - VolumeItem volumeItem = mVolumeItems.valueAt(i); - if (volumeItem.carVolumeItem == targetItem) { - return volumeItem; - } - } - return null; + private CarVolumeItem addCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId, + int supplementalIconId, + @Nullable View.OnClickListener supplementalIconOnClickListener) { + int seekbarProgressValue = getSeekbarValue(mCarAudioManager, volumeGroupId); + Drawable supplementalIcon = supplementalIconId == 0 ? null : mContext.getDrawable( + supplementalIconId); + CarVolumeItem carVolumeItem = createCarVolumeListItem(volumeItem, volumeGroupId, + supplementalIcon, seekbarProgressValue, supplementalIconOnClickListener); + mCarVolumeLineItems.add(carVolumeItem); + return carVolumeItem; } private void cleanupAudioManager() { @@ -530,21 +548,15 @@ public class CarVolumeDialogImpl implements VolumeDialog { for (int groupId = 0; groupId < mAvailableVolumeItems.size(); ++groupId) { if (groupId != mCurrentlyDisplayingGroupId) { VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); - addCarVolumeListItem(volumeItem, groupId, 0, null); + addCarVolumeListItem(volumeItem, groupId, /* supplementalIconId= */ 0, + /* supplementalIconOnClickListener= */ null); } } inAnimator = AnimatorInflater.loadAnimator( mContext, R.anim.car_arrow_fade_in_rotate_up); } else { - // Only keeping the default stream if it is not expended. - Iterator itr = mCarVolumeLineItems.iterator(); - while (itr.hasNext()) { - CarVolumeItem carVolumeItem = (CarVolumeItem) itr.next(); - if (carVolumeItem.getGroupId() != mCurrentlyDisplayingGroupId) { - itr.remove(); - } - } + clearAllAndSetupDefaultCarVolumeLineItem(mCurrentlyDisplayingGroupId); inAnimator = AnimatorInflater.loadAnimator( mContext, R.anim.car_arrow_fade_in_rotate_down); } diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 66e89237ac6d..a1ef831523b1 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1186,4 +1186,7 @@ <!-- Name of the this device. [CHAR LIMIT=30] --> <string name="media_transfer_this_device_name">This device</string> + + <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] --> + <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off & back on</string> </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 98db7c8fb59c..2507a3486f2b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -24,6 +24,9 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.SharedPreferences; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.ParcelUuid; import android.os.SystemClock; import android.text.TextUtils; @@ -55,6 +58,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> // Some Hearing Aids (especially the 2nd device) needs more time to do service discovery private static final long MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT = 15000; private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000; + private static final long MAX_MEDIA_PROFILE_CONNECT_DELAY = 60000; private final Context mContext; private final BluetoothAdapter mLocalAdapter; @@ -90,9 +94,35 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private boolean mIsActiveDeviceA2dp = false; private boolean mIsActiveDeviceHeadset = false; private boolean mIsActiveDeviceHearingAid = false; + // Media profile connect state + private boolean mIsA2dpProfileConnectedFail = false; + private boolean mIsHeadsetProfileConnectedFail = false; + private boolean mIsHearingAidProfileConnectedFail = false; // Group second device for Hearing Aid private CachedBluetoothDevice mSubDevice; + private final Handler mHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case BluetoothProfile.A2DP: + mIsA2dpProfileConnectedFail = true; + break; + case BluetoothProfile.HEADSET: + mIsHeadsetProfileConnectedFail = true; + break; + case BluetoothProfile.HEARING_AID: + mIsHearingAidProfileConnectedFail = true; + break; + default: + Log.w(TAG, "handleMessage(): unknown message : " + msg.what); + break; + } + Log.w(TAG, "Connect to profile : " + msg.what + " timeout, show error message !"); + refresh(); + } + }; + CachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager, BluetoothDevice device) { mContext = context; @@ -133,6 +163,35 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } synchronized (mProfileLock) { + if (profile instanceof A2dpProfile || profile instanceof HeadsetProfile + || profile instanceof HearingAidProfile) { + setProfileConnectedStatus(profile.getProfileId(), false); + switch (newProfileState) { + case BluetoothProfile.STATE_CONNECTED: + mHandler.removeMessages(profile.getProfileId()); + break; + case BluetoothProfile.STATE_CONNECTING: + mHandler.sendEmptyMessageDelayed(profile.getProfileId(), + MAX_MEDIA_PROFILE_CONNECT_DELAY); + break; + case BluetoothProfile.STATE_DISCONNECTING: + if (mHandler.hasMessages(profile.getProfileId())) { + mHandler.removeMessages(profile.getProfileId()); + } + break; + case BluetoothProfile.STATE_DISCONNECTED: + if (mHandler.hasMessages(profile.getProfileId())) { + mHandler.removeMessages(profile.getProfileId()); + setProfileConnectedStatus(profile.getProfileId(), true); + } + break; + default: + Log.w(TAG, "onProfileStateChanged(): unknown profile state : " + + newProfileState); + break; + } + } + if (newProfileState == BluetoothProfile.STATE_CONNECTED) { if (profile instanceof MapProfile) { profile.setPreferred(mDevice, true); @@ -162,6 +221,24 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> fetchActiveDevices(); } + @VisibleForTesting + void setProfileConnectedStatus(int profileId, boolean isFailed) { + switch (profileId) { + case BluetoothProfile.A2DP: + mIsA2dpProfileConnectedFail = isFailed; + break; + case BluetoothProfile.HEADSET: + mIsHeadsetProfileConnectedFail = isFailed; + break; + case BluetoothProfile.HEARING_AID: + mIsHearingAidProfileConnectedFail = isFailed; + break; + default: + Log.w(TAG, "setProfileConnectedStatus(): unknown profile id : " + profileId); + break; + } + } + public void disconnect() { synchronized (mProfileLock) { for (LocalBluetoothProfile profile : mProfiles) { @@ -844,6 +921,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> int leftBattery = -1; int rightBattery = -1; + if (isProfileConnectedFail() && isConnected()) { + return mContext.getString(R.string.profile_connect_timeout_subtext); + } + synchronized (mProfileLock) { for (LocalBluetoothProfile profile : getProfiles()) { int connectionStatus = getProfileConnectionState(profile); @@ -943,6 +1024,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> return leftBattery >= 0 && rightBattery >= 0; } + private boolean isProfileConnectedFail() { + return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail + || mIsHeadsetProfileConnectedFail; + } + /** * @return resource for android auto string that describes the connection state of this device. */ diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 93dcbfeab172..5c89a019bf82 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -31,6 +32,8 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.media.AudioManager; +import com.android.settingslib.R; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -922,4 +925,16 @@ public class CachedBluetoothDeviceTest { assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1); assertThat(subCachedDevice.mDevice).isEqualTo(mDevice); } + + @Test + public void getConnectionSummary_profileConnectedFail_showErrorMessage() { + final A2dpProfile profle = mock(A2dpProfile.class); + mCachedDevice.onProfileStateChanged(profle, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.setProfileConnectedStatus(BluetoothProfile.A2DP, true); + + when(profle.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED); + + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + mContext.getString(R.string.profile_connect_timeout_subtext)); + } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index d28c1aa4cfc4..55a51dab3f28 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -56,8 +56,6 @@ class SettingsProtoDumpUtil { ConfigSettingsProto.CONNECTIVITY_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, ConfigSettingsProto.CONTENT_CAPTURE_SETTINGS); - namespaceToFieldMap.put(DeviceConfig.NAMESPACE_DEX_BOOT, - ConfigSettingsProto.DEX_BOOT_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_GAME_DRIVER, ConfigSettingsProto.GAME_DRIVER_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT, diff --git a/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml b/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml index ff89bbcb455f..e9e844124e43 100644 --- a/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml +++ b/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml @@ -22,14 +22,16 @@ <application> <activity android:name=".PluginSettings" - android:label="@string/plugin_label"> + android:label="@string/plugin_label" + android:exported="false"> <intent-filter> <action android:name="com.android.systemui.action.PLUGIN_SETTINGS" /> </intent-filter> </activity> <service android:name=".SampleOverlayPlugin" - android:label="@string/plugin_label"> + android:label="@string/plugin_label" + android:exported="false"> <intent-filter> <action android:name="com.android.systemui.action.PLUGIN_OVERLAY" /> </intent-filter> diff --git a/packages/SystemUI/res/layout/home_controls.xml b/packages/SystemUI/res/layout/home_controls.xml index b9a6a482cf1a..69a0e872dc8c 100644 --- a/packages/SystemUI/res/layout/home_controls.xml +++ b/packages/SystemUI/res/layout/home_controls.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/home_controls_layout" android:layout_width="match_parent" - android:layout_height="125dp" + android:layout_height="wrap_content" android:layout_gravity="@integer/notification_panel_layout_gravity" android:visibility="gone" android:padding="8dp" diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml index 7d6ff3b16db6..69beffe0798c 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml @@ -20,7 +20,7 @@ android:id="@+id/plugin_frame" android:theme="@style/qs_theme" android:layout_width="@dimen/qs_panel_width" - android:layout_height="105dp" + android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/notification_side_paddings" android:layout_marginLeft="@dimen/notification_side_paddings" diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java index d6d1e418240a..37a447fc1957 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.Service; import com.android.systemui.SystemUI; +import com.android.systemui.recents.RecentsImplementation; /** * Interface necessary to make Dagger happy. See {@link ContextComponentResolver}. @@ -29,6 +30,9 @@ public interface ContextComponentHelper { Activity resolveActivity(String className); /** Turns a classname into an instance of the class or returns null. */ + RecentsImplementation resolveRecents(String className); + + /** Turns a classname into an instance of the class or returns null. */ Service resolveService(String className); /** Turns a classname into an instance of the class or returns null. */ diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java index d7822c9fc6da..06339bd5122e 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.Service; import com.android.systemui.SystemUI; +import com.android.systemui.recents.RecentsImplementation; import java.util.Map; @@ -35,15 +36,17 @@ public class ContextComponentResolver implements ContextComponentHelper { private final Map<Class<?>, Provider<Activity>> mActivityCreators; private final Map<Class<?>, Provider<Service>> mServiceCreators; private final Map<Class<?>, Provider<SystemUI>> mSystemUICreators; + private final Map<Class<?>, Provider<RecentsImplementation>> mRecentsCreators; @Inject - ContextComponentResolver( - Map<Class<?>, Provider<Activity>> activityCreators, + ContextComponentResolver(Map<Class<?>, Provider<Activity>> activityCreators, Map<Class<?>, Provider<Service>> serviceCreators, - Map<Class<?>, Provider<SystemUI>> systemUICreators) { + Map<Class<?>, Provider<SystemUI>> systemUICreators, + Map<Class<?>, Provider<RecentsImplementation>> recentsCreators) { mActivityCreators = activityCreators; mServiceCreators = serviceCreators; mSystemUICreators = systemUICreators; + mRecentsCreators = recentsCreators; } /** @@ -55,6 +58,14 @@ public class ContextComponentResolver implements ContextComponentHelper { } /** + * Looks up the RecentsImplementation class name to see if Dagger has an instance of it. + */ + @Override + public RecentsImplementation resolveRecents(String className) { + return resolve(className, mRecentsCreators); + } + + /** * Looks up the Service class name to see if Dagger has an instance of it. */ @Override diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java index 27c526b22283..c3d2a1f9b7dc 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java @@ -16,20 +16,89 @@ package com.android.systemui.dagger; +import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; + +import android.content.Context; +import android.os.PowerManager; +import android.util.DisplayMetrics; + +import com.android.internal.logging.MetricsLogger; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.ForegroundServiceController; import com.android.systemui.LatencyTester; import com.android.systemui.ScreenDecorations; import com.android.systemui.SystemUI; +import com.android.systemui.UiOffloadThread; +import com.android.systemui.appops.AppOpsController; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.pip.PipUI; +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.power.PowerUI; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsModule; +import com.android.systemui.statusbar.FeatureFlags; +import com.android.systemui.statusbar.NavigationBarController; +import com.android.systemui.statusbar.NotificationListener; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationViewHierarchyManager; +import com.android.systemui.statusbar.PulseExpansionHandler; +import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.VibratorHelper; +import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.NewNotifPipeline; +import com.android.systemui.statusbar.notification.NotificationAlertingManager; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; +import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.logging.NotifLog; +import com.android.systemui.statusbar.notification.logging.NotificationLogger; +import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.phone.AutoHideController; +import com.android.systemui.statusbar.phone.BiometricUnlockController; +import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.DozeScrimController; +import com.android.systemui.statusbar.phone.DozeServiceHost; +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; +import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.LightBarController; +import com.android.systemui.statusbar.phone.LockscreenWallpaper; +import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; +import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.statusbar.phone.StatusBarWindowViewController; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; +import com.android.systemui.statusbar.policy.UserSwitcherController; +import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.util.InjectionInflationController; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.volume.VolumeUI; +import javax.inject.Named; +import javax.inject.Singleton; + import dagger.Binds; +import dagger.Lazy; import dagger.Module; +import dagger.Provides; import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; @@ -93,4 +162,139 @@ public abstract class SystemUIBinder { @ClassKey(VolumeUI.class) public abstract SystemUI bindVolumeUI(VolumeUI sysui); + /** + * Provides our instance of StatusBar which is considered optional. + */ + @Provides + @Singleton + static StatusBar provideStatusBar( + Context context, + FeatureFlags featureFlags, + LightBarController lightBarController, + AutoHideController autoHideController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + StatusBarIconController statusBarIconController, + DozeLog dozeLog, + InjectionInflationController injectionInflationController, + PulseExpansionHandler pulseExpansionHandler, + NotificationWakeUpCoordinator notificationWakeUpCoordinator, + KeyguardBypassController keyguardBypassController, + KeyguardStateController keyguardStateController, + HeadsUpManagerPhone headsUpManagerPhone, + DynamicPrivacyController dynamicPrivacyController, + BypassHeadsUpNotifier bypassHeadsUpNotifier, + @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress, + Lazy<NewNotifPipeline> newNotifPipeline, + FalsingManager falsingManager, + BroadcastDispatcher broadcastDispatcher, + RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, + NotificationGutsManager notificationGutsManager, + NotificationLogger notificationLogger, + NotificationEntryManager notificationEntryManager, + NotificationInterruptionStateProvider notificationInterruptionStateProvider, + NotificationViewHierarchyManager notificationViewHierarchyManager, + ForegroundServiceController foregroundServiceController, + AppOpsController appOpsController, + KeyguardViewMediator keyguardViewMediator, + ZenModeController zenModeController, + NotificationAlertingManager notificationAlertingManager, + DisplayMetrics displayMetrics, + MetricsLogger metricsLogger, + UiOffloadThread uiOffloadThread, + NotificationMediaManager notificationMediaManager, + NotificationLockscreenUserManager lockScreenUserManager, + NotificationRemoteInputManager remoteInputManager, + UserSwitcherController userSwitcherController, + NetworkController networkController, + BatteryController batteryController, + SysuiColorExtractor colorExtractor, + ScreenLifecycle screenLifecycle, + WakefulnessLifecycle wakefulnessLifecycle, + SysuiStatusBarStateController statusBarStateController, + VibratorHelper vibratorHelper, + BubbleController bubbleController, + NotificationGroupManager groupManager, + NotificationGroupAlertTransferHelper groupAlertTransferHelper, + VisualStabilityManager visualStabilityManager, + DeviceProvisionedController deviceProvisionedController, + NavigationBarController navigationBarController, + AssistManager assistManager, + NotificationListener notificationListener, + ConfigurationController configurationController, + StatusBarWindowController statusBarWindowController, + StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder, + NotifLog notifLog, + DozeParameters dozeParameters, + ScrimController scrimController, + Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, + Lazy<BiometricUnlockController> biometricUnlockControllerLazy, + DozeServiceHost dozeServiceHost, + PowerManager powerManager, + DozeScrimController dozeScrimController) { + return new StatusBar( + context, + featureFlags, + lightBarController, + autoHideController, + keyguardUpdateMonitor, + statusBarIconController, + dozeLog, + injectionInflationController, + pulseExpansionHandler, + notificationWakeUpCoordinator, + keyguardBypassController, + keyguardStateController, + headsUpManagerPhone, + dynamicPrivacyController, + bypassHeadsUpNotifier, + allowNotificationLongPress, + newNotifPipeline, + falsingManager, + broadcastDispatcher, + remoteInputQuickSettingsDisabler, + notificationGutsManager, + notificationLogger, + notificationEntryManager, + notificationInterruptionStateProvider, + notificationViewHierarchyManager, + foregroundServiceController, + appOpsController, + keyguardViewMediator, + zenModeController, + notificationAlertingManager, + displayMetrics, + metricsLogger, + uiOffloadThread, + notificationMediaManager, + lockScreenUserManager, + remoteInputManager, + userSwitcherController, + networkController, + batteryController, + colorExtractor, + screenLifecycle, + wakefulnessLifecycle, + statusBarStateController, + vibratorHelper, + bubbleController, + groupManager, + groupAlertTransferHelper, + visualStabilityManager, + deviceProvisionedController, + navigationBarController, + assistManager, + notificationListener, + configurationController, + statusBarWindowController, + statusBarWindowViewControllerBuilder, + notifLog, + dozeParameters, + scrimController, + lockscreenWallpaperLazy, + biometricUnlockControllerLazy, + dozeServiceHost, + powerManager, + dozeScrimController); + } + } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index ca8e53deffdc..5f1455f63e54 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -26,11 +26,13 @@ import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.people.PeopleHubModule; import com.android.systemui.statusbar.phone.KeyguardLiftController; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.util.sensors.AsyncSensorManager; import javax.inject.Singleton; import dagger.Binds; +import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; @@ -65,4 +67,7 @@ public abstract class SystemUIModule { static SysUiState provideSysUiState() { return new SysUiState(); } + + @BindsOptionalOf + abstract StatusBar optionalStatusBar(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index a267bbb92ee7..a0ea7fae493d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -14,7 +14,6 @@ package com.android.systemui.qs; -import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.View.OnAttachStateChangeListener; @@ -31,6 +30,7 @@ import com.android.systemui.qs.TouchAnimator.Builder; import com.android.systemui.qs.TouchAnimator.Listener; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; +import com.android.systemui.util.Utils; import java.util.ArrayList; import java.util.Collection; @@ -270,9 +270,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } - int flag = Settings.System.getInt(mQsPanel.getContext().getContentResolver(), - "qs_media_player", 0); - if (flag == 1) { + if (Utils.useQsMediaPlayer(mQsPanel.getContext())) { View qsMediaView = mQsPanel.getMediaPanel(); View qqsMediaView = mQuickQsPanel.getMediaPlayer().getView(); translationXBuilder.addFloat(qsMediaView, "alpha", 0, 1); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index b48814bfd6bd..39f08650bf2c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -18,6 +18,7 @@ package com.android.systemui.qs; import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; +import static com.android.systemui.util.Utils.useQsMediaPlayer; import android.annotation.Nullable; import android.content.ComponentName; @@ -150,8 +151,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne addDivider(); // Add media carousel - int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0); - if (flag == 1) { + if (useQsMediaPlayer(context)) { HorizontalScrollView mediaScrollView = new HorizontalScrollView(mContext); mediaScrollView.setHorizontalScrollBarEnabled(false); int playerHeight = (int) getResources().getDimension(R.dimen.qs_media_height); @@ -201,8 +201,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne */ public void addMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor, View actionsContainer, StatusBarNotification notif) { - int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0); - if (flag != 1) { + if (!useQsMediaPlayer(mContext)) { // Shouldn't happen, but just in case Log.e(TAG, "Tried to add media session without player!"); return; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index dcd4633a79d2..94a1cf0c4e35 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -21,7 +21,6 @@ import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEX import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; -import android.provider.Settings; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -36,6 +35,7 @@ import com.android.systemui.plugins.qs.QSTile.State; import com.android.systemui.qs.customize.QSCustomizer; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; +import com.android.systemui.util.Utils; import java.util.ArrayList; import java.util.Collection; @@ -72,8 +72,7 @@ public class QuickQSPanel extends QSPanel { removeView((View) mTileLayout); } - int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0); - if (flag == 1) { + if (Utils.useQsMediaPlayer(context)) { LinearLayout mHorizontalLinearLayout = new LinearLayout(mContext); mHorizontalLinearLayout.setOrientation(LinearLayout.HORIZONTAL); mHorizontalLinearLayout.setClipChildren(false); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 592e3881ea97..16c61e60179e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -17,6 +17,7 @@ package com.android.systemui.qs; import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; +import static com.android.systemui.util.Utils.useQsMediaPlayer; import android.annotation.ColorInt; import android.app.ActivityManager; @@ -393,11 +394,10 @@ public class QuickStatusBarHeader extends RelativeLayout implements FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); - int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0); if (mQsDisabled) { lp.height = resources.getDimensionPixelSize( com.android.internal.R.dimen.quick_qs_offset_height); - } else if (flag == 1) { + } else if (useQsMediaPlayer(mContext)) { lp.height = Math.max(getMinimumHeight(), resources.getDimensionPixelSize( com.android.internal.R.dimen.quick_qs_total_height_with_media)); diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java index 958695d3b2ee..7f11e56ba168 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.trust.TrustManager; import android.content.Context; @@ -40,12 +41,22 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.phone.StatusBar; +import java.util.Optional; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import dagger.Lazy; + /** * An implementation of the Recents interface which proxies to the OverviewProxyService. */ +@Singleton public class OverviewProxyRecentsImpl implements RecentsImplementation { private final static String TAG = "OverviewProxyRecentsImpl"; + @Nullable + private final Lazy<StatusBar> mStatusBarLazy; private SysUiServiceProvider mSysUiServiceProvider; private Context mContext; @@ -53,6 +64,12 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation { private TrustManager mTrustManager; private OverviewProxyService mOverviewProxyService; + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + @Inject + public OverviewProxyRecentsImpl(Optional<Lazy<StatusBar>> statusBarLazy) { + mStatusBarLazy = statusBarLazy.orElse(null); + } + @Override public void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) { mContext = context; @@ -107,9 +124,8 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation { } }; // Preload only if device for current user is unlocked - final StatusBar statusBar = mSysUiServiceProvider.getComponent(StatusBar.class); - if (statusBar != null && statusBar.isKeyguardShowing()) { - statusBar.executeRunnableDismissingKeyguard(() -> { + if (mStatusBarLazy != null && mStatusBarLazy.get().isKeyguardShowing()) { + mStatusBarLazy.get().executeRunnableDismissingKeyguard(() -> { // Flush trustmanager before checking device locked per user mTrustManager.reportKeyguardShowingChanged(); mHandler.post(toggleRecents); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java index 3efed3fe2c4d..8cd17e9a1728 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java @@ -23,7 +23,10 @@ import com.android.systemui.SysUiServiceProvider; import java.io.PrintWriter; -interface RecentsImplementation { +/** + * API for creating a Recents view. + */ +public interface RecentsImplementation { default void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {} default void onBootCompleted() {} default void onAppTransitionFinished() {} diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java index 55552850890f..f57bfad890ff 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java @@ -19,35 +19,53 @@ package com.android.systemui.recents; import android.content.Context; import com.android.systemui.R; +import com.android.systemui.dagger.ContextComponentHelper; +import dagger.Binds; import dagger.Module; import dagger.Provides; +import dagger.multibindings.ClassKey; +import dagger.multibindings.IntoMap; /** * Dagger injection module for {@link RecentsImplementation} */ @Module -public class RecentsModule { +public abstract class RecentsModule { + /** * @return The {@link RecentsImplementation} from the config. */ @Provides - public RecentsImplementation provideRecentsImpl(Context context) { + public static RecentsImplementation provideRecentsImpl(Context context, + ContextComponentHelper componentHelper) { final String clsName = context.getString(R.string.config_recentsComponent); if (clsName == null || clsName.length() == 0) { throw new RuntimeException("No recents component configured", null); } - Class<?> cls = null; - try { - cls = context.getClassLoader().loadClass(clsName); - } catch (Throwable t) { - throw new RuntimeException("Error loading recents component: " + clsName, t); - } - try { - RecentsImplementation impl = (RecentsImplementation) cls.newInstance(); - return impl; - } catch (Throwable t) { - throw new RuntimeException("Error creating recents component: " + clsName, t); + RecentsImplementation impl = componentHelper.resolveRecents(clsName); + + if (impl == null) { + Class<?> cls = null; + try { + cls = context.getClassLoader().loadClass(clsName); + } catch (Throwable t) { + throw new RuntimeException("Error loading recents component: " + clsName, t); + } + try { + impl = (RecentsImplementation) cls.newInstance(); + } catch (Throwable t) { + throw new RuntimeException("Error creating recents component: " + clsName, t); + } } + + return impl; } + + /** */ + @Binds + @IntoMap + @ClassKey(OverviewProxyRecentsImpl.class) + public abstract RecentsImplementation bindOverviewProxyRecentsImpl( + OverviewProxyRecentsImpl impl); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index d6b87afc53b9..20a3e35791c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -21,7 +21,6 @@ import android.content.res.Resources; import android.os.Handler; import android.os.Trace; import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -40,6 +39,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.util.Assert; +import com.android.systemui.util.Utils; import java.util.ArrayList; import java.util.HashMap; @@ -146,9 +146,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle final int N = activeNotifications.size(); for (int i = 0; i < N; i++) { NotificationEntry ent = activeNotifications.get(i); - int flag = Settings.System.getInt(mContext.getContentResolver(), - "qs_media_player", 0); - boolean hideMedia = (flag == 1); + boolean hideMedia = Utils.useQsMediaPlayer(mContext); if (ent.isRowDismissed() || ent.isRowRemoved() || (ent.isMediaNotification() && hideMedia) || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.getKey())) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 9bc0ca440893..d0122c2b59b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -28,7 +28,6 @@ import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.metrics.LogMaker; import android.os.Handler; -import android.provider.Settings; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; @@ -48,6 +47,7 @@ import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.util.Utils; import java.util.Timer; import java.util.TimerTask; @@ -182,8 +182,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras .getParcelable(Notification.EXTRA_MEDIA_SESSION); - int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0); - if (flag == 1) { + if (Utils.useQsMediaPlayer(mContext)) { StatusBarWindowController ctrl = Dependency.get(StatusBarWindowController.class); QuickQSPanel panel = ctrl.getStatusBarView().findViewById( com.android.systemui.R.id.quick_qs_panel); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index e00cfb16bd67..467df375e7eb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -109,6 +109,7 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.InjectionInflationController; +import com.android.systemui.util.Utils; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -769,8 +770,7 @@ public class NotificationPanelView extends PanelView implements int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings); int topMargin = res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height); - int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0); - if (flag == 1) { + if (Utils.useQsMediaPlayer(mContext)) { topMargin = res.getDimensionPixelOffset( com.android.internal.R.dimen.quick_qs_total_height_with_media); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 35039a0d74f9..f21a9a2eba88 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -750,6 +750,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } private void onFinished(Callback callback) { + if (mPendingFrameCallback != null) { + // No animations can finish while we're waiting on the blanking to finish + return; + + } if (isAnimating(mScrimBehind) || isAnimating(mScrimInFront) || isAnimating(mScrimForBubble)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index afc147a75c56..001599ff37c7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -156,6 +156,7 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SystemUIBinder; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.fragments.ExtensionFragmentListener; @@ -246,14 +247,11 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.Map; -import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Lazy; import dagger.Subcomponent; -@Singleton public class StatusBar extends SystemUI implements DemoMode, ActivityStarter, KeyguardStateController.Callback, OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback, @@ -626,7 +624,12 @@ public class StatusBar extends SystemUI implements DemoMode, AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION}; - @Inject + /** + * Public constructor for StatusBar. + * + * StatusBar is considered optional, and therefore can not be marked as @Inject directly. + * Instead, an @Provide method is included in {@link SystemUIBinder}. + */ public StatusBar( Context context, FeatureFlags featureFlags, diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java index 92a8d8482e87..aa9c5ac2e032 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Utils.java +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -20,6 +20,7 @@ import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.provider.Settings; import android.view.View; import com.android.systemui.SysUiServiceProvider; @@ -124,4 +125,13 @@ public class Utils { && QuickStepContract.isGesturalMode(navMode); } + /** + * Allow the media player to be shown in the QS area, controlled by 2 flags. + */ + public static boolean useQsMediaPlayer(Context context) { + int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0); + flag |= Settings.System.getInt(context.getContentResolver(), "npv_plugin_flag", 0); + + return flag > 0; + } } diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 2bfe287c82b3..998572fc5679 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -72,6 +72,7 @@ filegroup { srcs: [ "src/com/android/server/connectivity/tethering/EntitlementManager.java", "src/com/android/server/connectivity/tethering/TetheringConfiguration.java", + "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java", ], } @@ -84,5 +85,6 @@ filegroup { "src/android/net/ip/IpServer.java", "src/android/net/ip/RouterAdvertisementDaemon.java", "src/android/net/util/InterfaceSet.java", + "src/android/net/util/PrefixUtils.java", ], } diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml index b9cac1994359..dc013da33869 100644 --- a/packages/Tethering/AndroidManifestBase.xml +++ b/packages/Tethering/AndroidManifestBase.xml @@ -23,7 +23,6 @@ <application android:label="Tethering" android:defaultToDeviceProtectedStorage="true" - android:directBootAware="true" - android:usesCleartextTraffic="true"> + android:directBootAware="true"> </application> </manifest> diff --git a/services/net/java/android/net/util/PrefixUtils.java b/packages/Tethering/src/android/net/util/PrefixUtils.java index f60694aaedc9..f203e9995f3d 100644 --- a/services/net/java/android/net/util/PrefixUtils.java +++ b/packages/Tethering/src/android/net/util/PrefixUtils.java @@ -42,16 +42,19 @@ public class PrefixUtils { public static final IpPrefix DEFAULT_WIFI_P2P_PREFIX = pfx("192.168.49.0/24"); + /** Get non forwardable prefixes. */ public static Set<IpPrefix> getNonForwardablePrefixes() { final HashSet<IpPrefix> prefixes = new HashSet<>(); addNonForwardablePrefixes(prefixes); return prefixes; } + /** Add non forwardable prefixes. */ public static void addNonForwardablePrefixes(Set<IpPrefix> prefixes) { Collections.addAll(prefixes, MIN_NON_FORWARDABLE_PREFIXES); } + /** Get local prefixes from |lp|. */ public static Set<IpPrefix> localPrefixesFrom(LinkProperties lp) { final HashSet<IpPrefix> localPrefixes = new HashSet<>(); if (lp == null) return localPrefixes; @@ -66,10 +69,12 @@ public class PrefixUtils { return localPrefixes; } + /** Convert LinkAddress |addr| to IpPrefix. */ public static IpPrefix asIpPrefix(LinkAddress addr) { return new IpPrefix(addr.getAddress(), addr.getPrefixLength()); } + /** Convert InetAddress |ip| to IpPrefix. */ public static IpPrefix ipAddressAsPrefix(InetAddress ip) { final int bitLength = (ip instanceof Inet4Address) ? NetworkConstants.IPV4_ADDR_BITS diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 3a9e21f943d8..9769596ab1d0 100644 --- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -146,6 +146,7 @@ public class UpstreamNetworkMonitor { } } + /** Listen all networks. */ public void startObserveAllNetworks() { stop(); @@ -155,6 +156,13 @@ public class UpstreamNetworkMonitor { cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); } + /** + * Stop tracking candidate tethering upstreams and release mobile network request. + * Note: this function is used when tethering is stopped because tethering do not need to + * choose upstream anymore. But it would not stop default network tracking because + * EntitlementManager may need to know default network to decide whether to request entitlement + * check even tethering is not active yet. + */ public void stop() { releaseMobileNetworkRequest(); @@ -165,6 +173,7 @@ public class UpstreamNetworkMonitor { mNetworkMap.clear(); } + /** Setup or teardown DUN connection according to |dunRequired|. */ public void updateMobileRequiresDun(boolean dunRequired) { final boolean valueChanged = (mDunRequired != dunRequired); mDunRequired = dunRequired; @@ -174,10 +183,12 @@ public class UpstreamNetworkMonitor { } } + /** Whether mobile network is requested. */ public boolean mobileNetworkRequested() { return (mMobileNetworkCallback != null); } + /** Request mobile network if mobile upstream is permitted. */ public void registerMobileNetworkRequest() { if (!isCellularUpstreamPermitted()) { mLog.i("registerMobileNetworkRequest() is not permitted"); @@ -209,6 +220,7 @@ public class UpstreamNetworkMonitor { cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler); } + /** Release mobile network request. */ public void releaseMobileNetworkRequest() { if (mMobileNetworkCallback == null) return; @@ -221,6 +233,9 @@ public class UpstreamNetworkMonitor { // becomes available and useful we (a) file a request to keep it up as // necessary and (b) change all upstream tracking state accordingly (by // passing LinkProperties up to Tethering). + /** + * Select the first available network from |perferredTypes|. + */ public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted()); @@ -254,7 +269,11 @@ public class UpstreamNetworkMonitor { return typeStatePair.ns; } - // Returns null if no current upstream available. + /** + * Get current preferred upstream network. If default network is cellular and DUN is required, + * preferred upstream would be DUN otherwise preferred upstream is the same as default network. + * Returns null if no current upstream is available. + */ public NetworkState getCurrentPreferredUpstream() { final NetworkState dfltState = (mDefaultInternetNetwork != null) ? mNetworkMap.get(mDefaultInternetNetwork) @@ -270,10 +289,12 @@ public class UpstreamNetworkMonitor { return findFirstDunNetwork(mNetworkMap.values()); } + /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */ public void setCurrentUpstream(Network upstream) { mTetheringUpstreamNetwork = upstream; } + /** Return local prefixes. */ public Set<IpPrefix> getLocalPrefixes() { return (Set<IpPrefix>) mLocalPrefixes.clone(); } @@ -501,8 +522,8 @@ public class UpstreamNetworkMonitor { try { nc = ConnectivityManager.networkCapabilitiesForType(type); } catch (IllegalArgumentException iae) { - Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + - ConnectivityManager.getNetworkTypeName(type)); + Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + + ConnectivityManager.getNetworkTypeName(type)); continue; } if (!isCellularUpstreamPermitted && isCellular(nc)) { @@ -547,18 +568,18 @@ public class UpstreamNetworkMonitor { } private static boolean isCellular(NetworkCapabilities nc) { - return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) && - nc.hasCapability(NET_CAPABILITY_NOT_VPN); + return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) + && nc.hasCapability(NET_CAPABILITY_NOT_VPN); } private static boolean hasCapability(NetworkState ns, int netCap) { - return (ns != null) && (ns.networkCapabilities != null) && - ns.networkCapabilities.hasCapability(netCap); + return (ns != null) && (ns.networkCapabilities != null) + && ns.networkCapabilities.hasCapability(netCap); } private static boolean isNetworkUsableAndNotCellular(NetworkState ns) { - return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) && - !isCellular(ns.networkCapabilities); + return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) + && !isCellular(ns.networkCapabilities); } private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) { diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index 5564bd6ecbca..7c06e5f0d7ce 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -47,6 +47,7 @@ filegroup { srcs: [ "src/com/android/server/connectivity/tethering/EntitlementManagerTest.java", "src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java", + "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java", "src/android/net/dhcp/DhcpServingParamsParcelExtTest.java", "src/android/net/ip/IpServerTest.java", "src/android/net/util/InterfaceSetTest.java", diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java index 0d276cbd1b85..c028d6d9cadc 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java @@ -87,7 +87,7 @@ public class UpstreamNetworkMonitorTest { // Actual contents of the request don't matter for this test. The lack of // any specific TRANSPORT_* is sufficient to identify this request. - private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build(); + private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build(); @Mock private Context mContext; @Mock private EntitlementManager mEntitleMgr; @@ -140,7 +140,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testDefaultNetworkIsTracked() throws Exception { assertTrue(mCM.hasNoCallbacks()); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertEquals(1, mCM.trackingDefault.size()); @@ -153,7 +153,7 @@ public class UpstreamNetworkMonitorTest { public void testListensForAllNetworks() throws Exception { assertTrue(mCM.listening.isEmpty()); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertFalse(mCM.listening.isEmpty()); assertTrue(mCM.isListeningForAll()); @@ -164,9 +164,9 @@ public class UpstreamNetworkMonitorTest { @Test public void testCallbacksRegistered() { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); verify(mCM, times(1)).requestNetwork( - eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class)); + eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class)); mUNM.startObserveAllNetworks(); verify(mCM, times(1)).registerNetworkCallback( any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class)); @@ -191,7 +191,7 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -217,7 +217,7 @@ public class UpstreamNetworkMonitorTest { assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); // Try a few things that must not result in any state change. mUNM.registerMobileNetworkRequest(); @@ -226,7 +226,7 @@ public class UpstreamNetworkMonitorTest { assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); mUNM.stop(); verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class)); @@ -250,7 +250,7 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -266,17 +266,17 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.updateMobileRequiresDun(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); // Test going from DUN to no-DUN correctly re-registers callbacks. mUNM.updateMobileRequiresDun(false); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -287,7 +287,7 @@ public class UpstreamNetworkMonitorTest { final Collection<Integer> preferredTypes = new ArrayList<>(); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // There are no networks, so there is nothing to select. assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); @@ -369,7 +369,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testGetCurrentPreferredUpstream() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); mUNM.updateMobileRequiresDun(false); @@ -418,7 +418,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testLocalPrefixes() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // [0] Test minimum set of local prefixes. @@ -431,13 +431,13 @@ public class UpstreamNetworkMonitorTest { final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); final LinkProperties wifiLp = wifiAgent.linkProperties; wifiLp.setInterfaceName("wlan0"); - final String[] WIFI_ADDRS = { + final String[] wifi_addrs = { "fe80::827a:bfff:fe6f:374d", "100.112.103.18", "2001:db8:4:fd00:827a:bfff:fe6f:374d", "2001:db8:4:fd00:6dea:325a:fdae:4ef4", "fd6a:a640:60bf:e985::123", // ULA address for good measure. }; - for (String addrStr : WIFI_ADDRS) { + for (String addrStr : wifi_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/20"; wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -458,10 +458,10 @@ public class UpstreamNetworkMonitorTest { final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); final LinkProperties cellLp = cellAgent.linkProperties; cellLp.setInterfaceName("rmnet_data0"); - final String[] CELL_ADDRS = { + final String[] cell_addrs = { "10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d", }; - for (String addrStr : CELL_ADDRS) { + for (String addrStr : cell_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/27"; cellLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -481,10 +481,10 @@ public class UpstreamNetworkMonitorTest { dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); final LinkProperties dunLp = dunAgent.linkProperties; dunLp.setInterfaceName("rmnet_data1"); - final String[] DUN_ADDRS = { + final String[] dun_addrs = { "192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d", }; - for (String addrStr : DUN_ADDRS) { + for (String addrStr : dun_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/27"; dunLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -525,7 +525,7 @@ public class UpstreamNetworkMonitorTest { // Mobile has higher pirority than wifi. preferredTypes.add(TYPE_MOBILE_HIPRI); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // Setup wifi and make wifi as default network. final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); @@ -556,6 +556,15 @@ public class UpstreamNetworkMonitorTest { mCM.legacyTypeMap.values().iterator().next()); } + private boolean isDunRequested() { + for (NetworkRequest req : mCM.requested.values()) { + if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { + return true; + } + } + return false; + } + public static class TestConnectivityManager extends ConnectivityManager { public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>(); public Set<NetworkCallback> trackingDefault = new HashSet<>(); @@ -598,17 +607,10 @@ public class UpstreamNetworkMonitorTest { return false; } - boolean isDunRequested() { - for (NetworkRequest req : requested.values()) { - if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { - return true; - } - } - return false; + int getNetworkId() { + return ++mNetworkId; } - int getNetworkId() { return ++mNetworkId; } - void makeDefaultNetwork(TestNetworkAgent agent) { if (Objects.equals(defaultNetwork, agent)) return; @@ -630,7 +632,7 @@ public class UpstreamNetworkMonitorTest { public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) { assertFalse(allCallbacks.containsKey(cb)); allCallbacks.put(cb, h); - if (mDefaultRequest.equals(req)) { + if (sDefaultRequest.equals(req)) { assertFalse(trackingDefault.contains(cb)); trackingDefault.add(cb); } else { @@ -749,9 +751,13 @@ public class UpstreamNetworkMonitorTest { private final State mLoggingState = new LoggingState(); class LoggingState extends State { - @Override public void enter() { messages.clear(); } + @Override public void enter() { + messages.clear(); + } - @Override public void exit() { messages.clear(); } + @Override public void exit() { + messages.clear(); + } @Override public boolean processMessage(Message msg) { messages.add(msg); diff --git a/services/core/Android.bp b/services/core/Android.bp index c86538438835..770de09382fe 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -115,7 +115,6 @@ java_library_static { "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", "dnsresolver_aidl_interface-V2-java", - "netd_aidl_interface-java", "netd_event_listener_interface-java", ], } diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index ff0044f6f1ad..e757b4e1a070 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -154,7 +154,7 @@ class AlarmManagerService extends SystemService { static final int TICK_HISTORY_DEPTH = 10; static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000; - // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays + // Indices into the KEYS_APP_STANDBY_QUOTAS array. static final int ACTIVE_INDEX = 0; static final int WORKING_INDEX = 1; static final int FREQUENT_INDEX = 2; @@ -401,8 +401,6 @@ class AlarmManagerService extends SystemService { static final String KEY_LISTENER_TIMEOUT = "listener_timeout"; @VisibleForTesting static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid"; - @VisibleForTesting - static final String KEY_APP_STANDBY_QUOTAS_ENABLED = "app_standby_quotas_enabled"; private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window"; @VisibleForTesting final String[] KEYS_APP_STANDBY_QUOTAS = { @@ -413,15 +411,6 @@ class AlarmManagerService extends SystemService { "standby_never_quota", }; - // Keys for specifying throttling delay based on app standby bucketing - private final String[] KEYS_APP_STANDBY_DELAY = { - "standby_active_delay", - "standby_working_delay", - "standby_frequent_delay", - "standby_rare_delay", - "standby_never_delay", - }; - private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS; @@ -430,7 +419,6 @@ class AlarmManagerService extends SystemService { private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000; private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000; private static final int DEFAULT_MAX_ALARMS_PER_UID = 500; - private static final boolean DEFAULT_APP_STANDBY_QUOTAS_ENABLED = true; private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000; // 1 hr /** * Max number of times an app can receive alarms in {@link #APP_STANDBY_WINDOW} @@ -442,13 +430,6 @@ class AlarmManagerService extends SystemService { 1, // Rare 0 // Never }; - private final long[] DEFAULT_APP_STANDBY_DELAYS = { - 0, // Active - 6 * 60_000, // Working - 30 * 60_000, // Frequent - 2 * 60 * 60_000, // Rare - 10 * 24 * 60 * 60_000 // Never - }; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; @@ -473,10 +454,7 @@ class AlarmManagerService extends SystemService { public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT; public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID; - public boolean APP_STANDBY_QUOTAS_ENABLED = DEFAULT_APP_STANDBY_QUOTAS_ENABLED; - public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW; - public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length]; public int[] APP_STANDBY_QUOTAS = new int[DEFAULT_APP_STANDBY_QUOTAS.length]; private ContentResolver mResolver; @@ -532,16 +510,6 @@ class AlarmManagerService extends SystemService { DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION); LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT); - APP_STANDBY_MIN_DELAYS[ACTIVE_INDEX] = mParser.getDurationMillis( - KEYS_APP_STANDBY_DELAY[ACTIVE_INDEX], - DEFAULT_APP_STANDBY_DELAYS[ACTIVE_INDEX]); - for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_DELAY.length; i++) { - APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i], - Math.max(APP_STANDBY_MIN_DELAYS[i - 1], DEFAULT_APP_STANDBY_DELAYS[i])); - } - - APP_STANDBY_QUOTAS_ENABLED = mParser.getBoolean(KEY_APP_STANDBY_QUOTAS_ENABLED, - DEFAULT_APP_STANDBY_QUOTAS_ENABLED); APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW, DEFAULT_APP_STANDBY_WINDOW); @@ -614,15 +582,6 @@ class AlarmManagerService extends SystemService { pw.print(KEY_MAX_ALARMS_PER_UID); pw.print("="); pw.println(MAX_ALARMS_PER_UID); - for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) { - pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("="); - TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw); - pw.println(); - } - - pw.print(KEY_APP_STANDBY_QUOTAS_ENABLED); pw.print("="); - pw.println(APP_STANDBY_QUOTAS_ENABLED); - pw.print(KEY_APP_STANDBY_WINDOW); pw.print("="); TimeUtils.formatDuration(APP_STANDBY_WINDOW, pw); pw.println(); @@ -1826,27 +1785,6 @@ class AlarmManagerService extends SystemService { } /** - * Return the minimum time that should elapse before an app in the specified bucket - * can receive alarms again - */ - @VisibleForTesting - long getMinDelayForBucketLocked(int bucket) { - // UsageStats bucket values are treated as floors of their behavioral range. - // In other words, a bucket value between WORKING and ACTIVE is treated as - // WORKING, not as ACTIVE. The ACTIVE and NEVER bucket apply only at specific - // values. - final int index; - - if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) index = NEVER_INDEX; - else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) index = RARE_INDEX; - else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) index = FREQUENT_INDEX; - else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) index = WORKING_INDEX; - else index = ACTIVE_INDEX; - - return mConstants.APP_STANDBY_MIN_DELAYS[index]; - } - - /** * Adjusts the alarm delivery time based on the current app standby bucket. * @param alarm The alarm to adjust * @return true if the alarm delivery time was updated. @@ -1872,50 +1810,34 @@ class AlarmManagerService extends SystemService { final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket( sourcePackage, sourceUserId, mInjector.getElapsedRealtime()); - if (mConstants.APP_STANDBY_QUOTAS_ENABLED) { - // Quota deferring implementation: - final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage, - sourceUserId); - final int quotaForBucket = getQuotaForBucketLocked(standbyBucket); - boolean deferred = false; - if (wakeupsInWindow >= quotaForBucket) { - final long minElapsed; - if (quotaForBucket <= 0) { - // Just keep deferring for a day till the quota changes - minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY; - } else { - // Suppose the quota for window was q, and the qth last delivery time for this - // package was t(q) then the next delivery must be after t(q) + <window_size> - final long t = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, - sourceUserId, quotaForBucket); - minElapsed = t + 1 + mConstants.APP_STANDBY_WINDOW; - } - if (alarm.expectedWhenElapsed < minElapsed) { - alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; - deferred = true; - } - } - if (!deferred) { - // Restore original requirements in case they were changed earlier. - alarm.whenElapsed = alarm.expectedWhenElapsed; - alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; + // Quota deferring implementation: + final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage, + sourceUserId); + final int quotaForBucket = getQuotaForBucketLocked(standbyBucket); + boolean deferred = false; + if (wakeupsInWindow >= quotaForBucket) { + final long minElapsed; + if (quotaForBucket <= 0) { + // Just keep deferring for a day till the quota changes + minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY; + } else { + // Suppose the quota for window was q, and the qth last delivery time for this + // package was t(q) then the next delivery must be after t(q) + <window_size> + final long t = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, + sourceUserId, quotaForBucket); + minElapsed = t + 1 + mConstants.APP_STANDBY_WINDOW; } - } else { - // Minimum delay deferring implementation: - final long lastElapsed = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, - sourceUserId, 1); - if (lastElapsed > 0) { - final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket); - if (alarm.expectedWhenElapsed < minElapsed) { - alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; - } else { - // app is now eligible to run alarms at the originally requested window. - // Restore original requirements in case they were changed earlier. - alarm.whenElapsed = alarm.expectedWhenElapsed; - alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; - } + if (alarm.expectedWhenElapsed < minElapsed) { + alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; + deferred = true; } } + if (!deferred) { + // Restore original requirements in case they were changed earlier. + alarm.whenElapsed = alarm.expectedWhenElapsed; + alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; + } + return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed); } @@ -4446,7 +4368,8 @@ class AlarmManagerService extends SystemService { } final class UidObserver extends IUidObserver.Stub { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { + @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, + int capability) { } @Override public void onUidGone(int uid, boolean disabled) { diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java index 5eff2c5c1d37..486cd5fee01c 100644 --- a/services/core/java/com/android/server/AppStateTracker.java +++ b/services/core/java/com/android/server/AppStateTracker.java @@ -632,7 +632,7 @@ public class AppStateTracker { private final class UidObserver extends IUidObserver.Stub { @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) { + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { mHandler.onUidStateChanged(uid, procState); } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 7712f1b4a9a0..39f039af330c 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -128,6 +128,32 @@ import java.util.concurrent.TimeUnit; * updates and alerts. */ public class LocationManagerService extends ILocationManager.Stub { + + /** + * Controls lifecycle of LocationManagerService. + */ + public static class Lifecycle extends SystemService { + + private LocationManagerService mService; + + public Lifecycle(Context context) { + super(context); + mService = new LocationManagerService(context); + } + + @Override + public void onStart() { + publishBinderService(Context.LOCATION_SERVICE, mService); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { + mService.systemRunning(); + } + } + } + private static final String TAG = "LocationManagerService"; public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); @@ -234,8 +260,7 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") private final LocationUsageLogger mLocationUsageLogger; - public LocationManagerService(Context context) { - super(); + private LocationManagerService(Context context) { mContext = context; mHandler = FgThread.getHandler(); mLocationUsageLogger = new LocationUsageLogger(); @@ -254,7 +279,7 @@ public class LocationManagerService extends ILocationManager.Stub { // most startup is deferred until systemRunning() } - public void systemRunning() { + private void systemRunning() { synchronized (mLock) { initializeLocked(); } @@ -1453,6 +1478,16 @@ public class LocationManagerService extends ILocationManager.Stub { return true; } + public void callRemovedLocked() { + if (mListener != null) { + try { + mListener.onRemoved(); + } catch (RemoteException e) { + // doesn't matter + } + } + } + @Override public void binderDied() { if (D) Log.d(TAG, "Remote " + mListenerName + " died."); @@ -3066,6 +3101,8 @@ public class LocationManagerService extends ILocationManager.Stub { // track expired records if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) { + // notify the client it can remove this listener + r.mReceiver.callRemovedLocked(); if (deadUpdateRecords == null) { deadUpdateRecords = new ArrayList<>(); } diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index 49ef1642c051..d5f795683675 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -333,8 +333,8 @@ public final class PinnerService extends SystemService { } @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) - throws RemoteException { + public void onUidStateChanged(int uid, int procState, long procStateSeq, + int capability) throws RemoteException { } @Override diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index d622fb433ed8..b8acd7ac108a 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -174,7 +174,8 @@ public class VibratorService extends IVibratorService.Stub static native long vibratorGetCapabilities(); private final IUidObserver mUidObserver = new IUidObserver.Stub() { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { + @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, + int capability) { mProcStatesCache.put(uid, procState); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 4f54e64f6911..b5cab1f8d62b 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3248,7 +3248,7 @@ public class AccountManagerService UserAccounts accounts = getUserAccounts(userId); logRecordWithUid( accounts, AccountsDb.DEBUG_ACTION_CALLED_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS, - userId); + uid); new Session(accounts, response, accountType, expectActivityLaunch, true /* stripAuthTokenFromResult */, null /* accountName */, false /* authDetailsRequired */, true /* updateLastAuthenticationTime */) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5df45437ae34..d6ecdeac1654 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -139,6 +139,7 @@ import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToS import android.Manifest; import android.Manifest.permission; +import android.annotation.BroadcastBehavior; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -299,10 +300,8 @@ import android.view.View; import android.view.WindowManager; import android.view.autofill.AutofillManagerInternal; -import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.DumpHeapActivity; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import com.android.internal.app.ProcessMap; @@ -503,6 +502,41 @@ public class ActivityManagerService extends IActivityManager.Stub static final int PERSISTENT_MASK = ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT; + // Intent sent when remote bugreport collection has been completed + private static final String INTENT_REMOTE_BUGREPORT_FINISHED = + "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED"; + + /** + * Broadcast sent when heap dump collection has been completed. + */ + @BroadcastBehavior(includeBackground = true, protectedBroadcast = true) + private static final String ACTION_HEAP_DUMP_FINISHED = + "com.android.internal.intent.action.HEAP_DUMP_FINISHED"; + + /** + * The process we are reporting + */ + private static final String EXTRA_HEAP_DUMP_PROCESS_NAME = + "com.android.internal.extra.heap_dump.PROCESS_NAME"; + + /** + * The size limit the process reached. + */ + private static final String EXTRA_HEAP_DUMP_SIZE_BYTES = + "com.android.internal.extra.heap_dump.SIZE_BYTES"; + + /** + * Whether the user initiated the dump or not. + */ + private static final String EXTRA_HEAP_DUMP_IS_USER_INITIATED = + "com.android.internal.extra.heap_dump.IS_USER_INITIATED"; + + /** + * Optional name of package to directly launch. + */ + private static final String EXTRA_HEAP_DUMP_REPORT_PACKAGE = + "com.android.internal.extra.heap_dump.REPORT_PACKAGE"; + // If set, we will push process association information in to procstats. static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true; @@ -1332,7 +1366,7 @@ public class ActivityManagerService extends IActivityManager.Stub int mProfileType = 0; final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>(); String mMemWatchDumpProcName; - String mMemWatchDumpFile; + Uri mMemWatchDumpUri; int mMemWatchDumpPid; int mMemWatchDumpUid; private boolean mMemWatchIsUserInitiated; @@ -1344,10 +1378,12 @@ public class ActivityManagerService extends IActivityManager.Stub static final class ProcessChangeItem { static final int CHANGE_ACTIVITIES = 1<<0; static final int CHANGE_FOREGROUND_SERVICES = 1<<1; + static final int CHANGE_CAPABILITY = 1<<2; int changes; int uid; int pid; int processState; + int capability; boolean foregroundActivities; int foregroundServiceTypes; } @@ -1519,7 +1555,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int UPDATE_TIME_PREFERENCE_MSG = 41; static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49; static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50; - static final int DELETE_DUMPHEAP_MSG = 51; + static final int ABORT_DUMPHEAP_MSG = 51; static final int DISPATCH_UIDS_CHANGED_UI_MSG = 53; static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 56; static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 57; @@ -1788,11 +1824,7 @@ public class ActivityManagerService extends IActivityManager.Stub final boolean isUserInitiated; synchronized (ActivityManagerService.this) { uid = mMemWatchDumpUid; - if (uid == SYSTEM_UID) { - procName = mContext.getString(R.string.android_system_label); - } else { - procName = mMemWatchDumpProcName; - } + procName = mMemWatchDumpProcName; Pair<Long, String> val = mMemWatchProcesses.get(procName, uid); if (val == null) { val = mMemWatchProcesses.get(procName, 0); @@ -1805,6 +1837,11 @@ public class ActivityManagerService extends IActivityManager.Stub reportPackage = null; } isUserInitiated = mMemWatchIsUserInitiated; + + mMemWatchDumpUri = null; + mMemWatchDumpProcName = null; + mMemWatchDumpPid = -1; + mMemWatchDumpUid = -1; } if (procName == null) { return; @@ -1813,65 +1850,29 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_PSS) Slog.d(TAG_PSS, "Showing dump heap notification from " + procName + "/" + uid); - INotificationManager inm = NotificationManager.getService(); - if (inm == null) { - return; - } - - final int titleId = isUserInitiated - ? R.string.dump_heap_ready_notification : R.string.dump_heap_notification; - String text = mContext.getString(titleId, procName); - - Intent deleteIntent = new Intent(); - deleteIntent.setAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP); - Intent intent = new Intent(); - intent.setClassName("android", DumpHeapActivity.class.getName()); - intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName); - intent.putExtra(DumpHeapActivity.KEY_SIZE, memLimit); - intent.putExtra(DumpHeapActivity.KEY_IS_USER_INITIATED, isUserInitiated); - intent.putExtra(DumpHeapActivity.KEY_IS_SYSTEM_PROCESS, uid == SYSTEM_UID); - if (reportPackage != null) { - intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage); - } - int userId = UserHandle.getUserId(uid); - Notification notification = - new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER) - .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) - .setAutoCancel(true) - .setTicker(text) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)) - .setContentTitle(text) - .setContentText( - mContext.getText(R.string.dump_heap_notification_detail)) - .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, - intent, PendingIntent.FLAG_CANCEL_CURRENT, null, - new UserHandle(userId))) - .setDeleteIntent(PendingIntent.getBroadcastAsUser(mContext, 0, - deleteIntent, 0, UserHandle.SYSTEM)) - .build(); - - try { - inm.enqueueNotificationWithTag("android", "android", null, - SystemMessage.NOTE_DUMP_HEAP_NOTIFICATION, - notification, userId); - } catch (RuntimeException e) { - Slog.w(ActivityManagerService.TAG, - "Error showing notification for dump heap", e); - } catch (RemoteException e) { - } + Intent dumpFinishedIntent = new Intent(ACTION_HEAP_DUMP_FINISHED); + // Send this only to the Shell package. + dumpFinishedIntent.setPackage("com.android.shell"); + dumpFinishedIntent.putExtra(Intent.EXTRA_UID, uid); + dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_IS_USER_INITIATED, isUserInitiated); + dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_SIZE_BYTES, memLimit); + dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_REPORT_PACKAGE, reportPackage); + dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_PROCESS_NAME, procName); + + mContext.sendBroadcastAsUser(dumpFinishedIntent, + UserHandle.getUserHandleForUid(uid)); } break; - case DELETE_DUMPHEAP_MSG: { - revokeUriPermission(ActivityThread.currentActivityThread().getApplicationThread(), - null, DumpHeapActivity.JAVA_URI, - Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_WRITE_URI_PERMISSION, - UserHandle.myUserId()); - synchronized (ActivityManagerService.this) { - mMemWatchDumpFile = null; - mMemWatchDumpProcName = null; - mMemWatchDumpPid = -1; - mMemWatchDumpUid = -1; + case ABORT_DUMPHEAP_MSG: { + String procName = (String) msg.obj; + if (procName != null) { + synchronized (ActivityManagerService.this) { + if (procName.equals(mMemWatchDumpProcName)) { + mMemWatchDumpProcName = null; + mMemWatchDumpUri = null; + mMemWatchDumpPid = -1; + mMemWatchDumpUid = -1; + } + } } } break; case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: { @@ -3337,6 +3338,7 @@ public class ActivityManagerService extends IActivityManager.Stub validateUid.idle = false; } validateUid.setCurProcState(validateUid.setProcState = item.processState); + validateUid.curCapability = validateUid.setCapability = item.capability; validateUid.lastDispatchedProcStateSeq = item.procStateSeq; } } @@ -3402,7 +3404,7 @@ public class ActivityManagerService extends IActivityManager.Stub if ((reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "UID CHANGED uid=" + item.uid - + ": " + item.processState); + + ": " + item.processState + ": " + item.capability); boolean doReport = true; if (reg.cutpoint >= ActivityManager.MIN_PROCESS_STATE) { final int lastState = reg.lastProcStates.get(item.uid, @@ -3420,7 +3422,7 @@ public class ActivityManagerService extends IActivityManager.Stub reg.lastProcStates.put(item.uid, item.processState); } observer.onUidStateChanged(item.uid, item.processState, - item.procStateSeq); + item.procStateSeq, item.capability); } } } @@ -5245,17 +5247,6 @@ public class ActivityManagerService extends IActivityManager.Stub } }, pkgFilter); - IntentFilter dumpheapFilter = new IntentFilter(); - dumpheapFilter.addAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final long delay = intent.getBooleanExtra( - DumpHeapActivity.EXTRA_DELAY_DELETE, false) ? 5 * 60 * 1000 : 0; - mHandler.sendEmptyMessageDelayed(DELETE_DUMPHEAP_MSG, delay); - } - }, dumpheapFilter); - // Inform checkpointing systems of success try { // This line is needed to CTS test for the correct exception handling @@ -10953,7 +10944,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName); - pw.print(" mMemWatchDumpFile="); pw.println(mMemWatchDumpFile); + pw.print(" mMemWatchDumpUri="); pw.println(mMemWatchDumpUri); pw.print(" mMemWatchDumpPid="); pw.println(mMemWatchDumpPid); pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid); pw.print(" mMemWatchIsUserInitiated="); pw.println(mMemWatchIsUserInitiated); @@ -11250,10 +11241,14 @@ public class ActivityManagerService extends IActivityManager.Stub } final long dtoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP); - proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME, mMemWatchDumpProcName); - proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.FILE, mMemWatchDumpFile); - proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID, mMemWatchDumpPid); - proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID, mMemWatchDumpUid); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME, + mMemWatchDumpProcName); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.URI, + mMemWatchDumpUri.toString()); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID, + mMemWatchDumpPid); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID, + mMemWatchDumpUid); proto.write( ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.IS_USER_INITIATED, mMemWatchIsUserInitiated); @@ -16366,9 +16361,10 @@ public class ActivityManagerService extends IActivityManager.Stub } } - void noteUidProcessState(final int uid, final int state) { + void noteUidProcessState(final int uid, final int state, + final @ActivityManager.ProcessCapability int capability) { mBatteryStatsService.noteUidProcessState(uid, state); - mAppOpsService.updateUidProcState(uid, state); + mAppOpsService.updateUidProcState(uid, state, capability); if (mTrackingAssociations) { for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) { ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents @@ -16395,56 +16391,44 @@ public class ActivityManagerService extends IActivityManager.Stub } } - private static final class RecordPssRunnable implements Runnable { - private final ActivityManagerService mService; + /** @hide */ + public static Uri makeHeapDumpUri(String procName) { + return Uri.parse("content://com.android.shell.heapdump/" + procName + "_javaheap.bin"); + } + + private final class RecordPssRunnable implements Runnable { private final ProcessRecord mProc; - private final File mHeapdumpFile; + private final Uri mDumpUri; + private final ContentResolver mContentResolver; - RecordPssRunnable(ActivityManagerService service, ProcessRecord proc, File heapdumpFile) { - this.mService = service; - this.mProc = proc; - this.mHeapdumpFile = heapdumpFile; + RecordPssRunnable(ProcessRecord proc, Uri dumpUri, ContentResolver contentResolver) { + mProc = proc; + mDumpUri = dumpUri; + mContentResolver = contentResolver; } @Override public void run() { - mService.revokeUriPermission(ActivityThread.currentActivityThread() - .getApplicationThread(), - null, DumpHeapActivity.JAVA_URI, - Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_WRITE_URI_PERMISSION, - UserHandle.myUserId()); - ParcelFileDescriptor fd = null; - try { - mHeapdumpFile.delete(); - fd = ParcelFileDescriptor.open(mHeapdumpFile, - ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_TRUNCATE - | ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_APPEND); + try (ParcelFileDescriptor fd = mContentResolver.openFileDescriptor(mDumpUri, "rw")) { IApplicationThread thread = mProc.thread; if (thread != null) { try { if (DEBUG_PSS) { Slog.d(TAG_PSS, "Requesting dump heap from " - + mProc + " to " + mHeapdumpFile); + + mProc + " to " + mDumpUri.getPath()); } thread.dumpHeap(/* managed= */ true, /* mallocInfo= */ false, /* runGc= */ false, - mHeapdumpFile.toString(), fd, + mDumpUri.getPath(), fd, /* finishCallback= */ null); } catch (RemoteException e) { } } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } finally { - if (fd != null) { - try { - fd.close(); - } catch (IOException e) { - } - } + } catch (IOException e) { + Slog.e(TAG, "Failed to dump heap", e); + // Need to clear the heap dump variables, otherwise no further heap dumps will be + // attempted. + abortHeapDump(mProc.processName); } } } @@ -16513,13 +16497,20 @@ public class ActivityManagerService extends IActivityManager.Stub } private void startHeapDumpLocked(ProcessRecord proc, boolean isUserInitiated) { - final File heapdumpFile = DumpHeapProvider.getJavaFile(); mMemWatchDumpProcName = proc.processName; - mMemWatchDumpFile = heapdumpFile.toString(); + mMemWatchDumpUri = makeHeapDumpUri(proc.processName); mMemWatchDumpPid = proc.pid; mMemWatchDumpUid = proc.uid; mMemWatchIsUserInitiated = isUserInitiated; - BackgroundThread.getHandler().post(new RecordPssRunnable(this, proc, heapdumpFile)); + Context ctx; + try { + ctx = mContext.createPackageContextAsUser("android", 0, + UserHandle.getUserHandleForUid(mMemWatchDumpUid)); + } catch (NameNotFoundException e) { + throw new RuntimeException("android package not found."); + } + BackgroundThread.getHandler().post( + new RecordPssRunnable(proc, mMemWatchDumpUri, ctx.getContentResolver())); } /** @@ -16891,6 +16882,7 @@ public class ActivityManagerService extends IActivityManager.Stub } pendingChange.change = change; pendingChange.processState = uidRec != null ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT; + pendingChange.capability = uidRec != null ? uidRec.setCapability : 0; pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid); pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0; if (uidRec != null) { @@ -17715,9 +17707,9 @@ public class ActivityManagerService extends IActivityManager.Stub + " does not match last pid " + mMemWatchDumpPid); return; } - if (mMemWatchDumpFile == null || !mMemWatchDumpFile.equals(path)) { + if (mMemWatchDumpUri == null || !mMemWatchDumpUri.getPath().equals(path)) { Slog.w(TAG, "dumpHeapFinished: Calling path " + path - + " does not match last path " + mMemWatchDumpFile); + + " does not match last path " + mMemWatchDumpUri); return; } if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path); @@ -17728,6 +17720,13 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** Clear the currently executing heap dump variables so a new heap dump can be started. */ + private void abortHeapDump(String procName) { + Message msg = mHandler.obtainMessage(ABORT_DUMPHEAP_MSG); + msg.obj = procName; + mHandler.sendMessage(msg); + } + /** In this method we try to acquire our lock to make sure that we have not deadlocked */ public void monitor() { synchronized (this) { } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 8be2438b4f2f..59acdcf4a875 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -1470,7 +1470,8 @@ final class ActivityManagerShellCommand extends ShellCommand { } @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException { + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) + throws RemoteException { synchronized (this) { final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); try { @@ -1478,7 +1479,9 @@ final class ActivityManagerShellCommand extends ShellCommand { mPw.print(" procstate "); mPw.print(ProcessList.makeProcStateString(procState)); mPw.print(" seq "); - mPw.println(procStateSeq); + mPw.print(procStateSeq); + mPw.print(" capability "); + mPw.println(capability); mPw.flush(); } finally { StrictMode.setThreadPolicy(oldPolicy); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 6a29c75b702a..8095020ce4ce 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -383,7 +383,11 @@ class AppErrors { // and then the delayed summary kill will be a no-op. final ProcessRecord p = proc; mService.mHandler.postDelayed( - () -> killAppImmediateLocked(p, "forced", "killed for invalid state"), + () -> { + synchronized (mService) { + killAppImmediateLocked(p, "forced", "killed for invalid state"); + } + }, 5000L); } } diff --git a/services/core/java/com/android/server/am/DumpHeapProvider.java b/services/core/java/com/android/server/am/DumpHeapProvider.java deleted file mode 100644 index a8b639ecf8d4..000000000000 --- a/services/core/java/com/android/server/am/DumpHeapProvider.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2015 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.am; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; -import android.os.Environment; -import android.os.ParcelFileDescriptor; - -import java.io.File; -import java.io.FileNotFoundException; - -public class DumpHeapProvider extends ContentProvider { - static final Object sLock = new Object(); - static File sHeapDumpJavaFile; - - static public File getJavaFile() { - synchronized (sLock) { - return sHeapDumpJavaFile; - } - } - - @Override - public boolean onCreate() { - synchronized (sLock) { - File dataDir = Environment.getDataDirectory(); - File systemDir = new File(dataDir, "system"); - File heapdumpDir = new File(systemDir, "heapdump"); - heapdumpDir.mkdir(); - sHeapDumpJavaFile = new File(heapdumpDir, "javaheap.bin"); - } - return true; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return "application/octet-stream"; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - synchronized (sLock) { - String path = uri.getEncodedPath(); - final String tag = Uri.decode(path); - if (tag.equals("/java")) { - return ParcelFileDescriptor.open(sHeapDumpJavaFile, - ParcelFileDescriptor.MODE_READ_ONLY); - } else { - throw new FileNotFoundException("Invalid path for " + uri); - } - } - } -} diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 78a9efc6e2a7..f610d7d63b6c 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -16,6 +16,9 @@ package com.android.server.am; +import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; +import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; @@ -23,7 +26,6 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT; import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; -import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; @@ -65,6 +67,7 @@ import android.app.ActivityManager; import android.app.usage.UsageEvents; import android.content.Context; import android.content.pm.ServiceInfo; +import android.os.Build; import android.os.Debug; import android.os.Handler; import android.os.IBinder; @@ -471,6 +474,7 @@ public final class OomAdjuster { app.containsCycle = false; app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); app.setCurRawAdj(ProcessList.UNKNOWN_ADJ); + app.setCapability = PROCESS_CAPABILITY_NONE; app.resetCachedInfo(); } for (int i = numProc - 1; i >= 0; i--) { @@ -788,6 +792,7 @@ public final class OomAdjuster { if (app.hasForegroundServices()) { uidRec.foregroundServices = true; } + uidRec.curCapability |= app.curCapability; } } @@ -804,10 +809,13 @@ public final class OomAdjuster { int uidChange = UidRecord.CHANGE_PROCSTATE; if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT && (uidRec.setProcState != uidRec.getCurProcState() + || uidRec.setCapability != uidRec.curCapability || uidRec.setWhitelist != uidRec.curWhitelist)) { if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec + ": proc state from " + uidRec.setProcState + " to " - + uidRec.getCurProcState() + ", whitelist from " + uidRec.setWhitelist + + uidRec.getCurProcState() + ", capability from " + + uidRec.setCapability + " to " + uidRec.curCapability + + ", whitelist from " + uidRec.setWhitelist + " to " + uidRec.curWhitelist); if (ActivityManager.isProcStateBackground(uidRec.getCurProcState()) && !uidRec.curWhitelist) { @@ -845,11 +853,13 @@ public final class OomAdjuster { uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED; } uidRec.setProcState = uidRec.getCurProcState(); + uidRec.setCapability = uidRec.curCapability; uidRec.setWhitelist = uidRec.curWhitelist; uidRec.setIdle = uidRec.idle; mService.mAtmInternal.onUidProcStateChanged(uidRec.uid, uidRec.setProcState); mService.enqueueUidChangeLocked(uidRec, -1, uidChange); - mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState()); + mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(), + uidRec.curCapability); if (uidRec.foregroundServices) { mService.mServices.foregroundServiceProcStateChangedLocked(uidRec); } @@ -1016,6 +1026,7 @@ public final class OomAdjuster { app.curAdj = ProcessList.CACHED_APP_MAX_ADJ; app.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ); app.completedAdjSeq = app.adjSeq; + app.curCapability = PROCESS_CAPABILITY_NONE; return false; } @@ -1030,6 +1041,7 @@ public final class OomAdjuster { int prevAppAdj = app.curAdj; int prevProcState = app.getCurProcState(); + int prevCapability = app.curCapability; if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { // The max adjustment doesn't allow this app to be anything @@ -1087,6 +1099,7 @@ public final class OomAdjuster { int schedGroup; int procState; int cachedAdjSeq; + int capability = 0; boolean foregroundActivities = false; if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) { @@ -1185,19 +1198,17 @@ public final class OomAdjuster { } } + if (app.hasLocationForegroundServices()) { + capability |= PROCESS_CAPABILITY_FOREGROUND_LOCATION; + } + if (adj > ProcessList.PERCEPTIBLE_APP_ADJ - || procState > PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) { + || procState > PROCESS_STATE_FOREGROUND_SERVICE) { if (app.hasForegroundServices()) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; - if (app.hasLocationForegroundServices()) { - procState = PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; - app.adjType = "fg-service-location"; - - } else { - procState = PROCESS_STATE_FOREGROUND_SERVICE; - app.adjType = "fg-service"; - } + procState = PROCESS_STATE_FOREGROUND_SERVICE; + app.adjType = "fg-service"; app.cached = false; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { @@ -1437,6 +1448,10 @@ public final class OomAdjuster { continue; } + if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { + capability |= client.curCapability; + } + int clientAdj = client.getCurRawAdj(); int clientProcState = client.getCurRawProcState(); @@ -1549,25 +1564,31 @@ public final class OomAdjuster { // processes). These should not bring the current process // into the top state, since they are not on top. Instead // give them the best bound state after that. - final int bestState = cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES) - ? PROCESS_STATE_FOREGROUND_SERVICE_LOCATION - : PROCESS_STATE_BOUND_FOREGROUND_SERVICE; - if ((cr.flags & Context.BIND_FOREGROUND_SERVICE) != 0) { - clientProcState = bestState; + if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) { + clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; ; } else if (mService.mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0) { - clientProcState = bestState; + clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } else { clientProcState = PROCESS_STATE_IMPORTANT_FOREGROUND; } } else if (clientProcState == PROCESS_STATE_TOP) { - if (cr.notHasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { - // Go at most to BOUND_TOP, unless requested to elevate - // to client's state. - clientProcState = PROCESS_STATE_BOUND_TOP; + // Go at most to BOUND_TOP, unless requested to elevate + // to client's state. + clientProcState = PROCESS_STATE_BOUND_TOP; + if (client.info.targetSdkVersion >= Build.VERSION_CODES.R) { + if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { + // TOP process passes all capabilities to the service. + capability = PROCESS_CAPABILITY_ALL; + } else { + // TOP process passes no capability to the service. + } + } else { + // TOP process passes all capabilities to the service. + capability = PROCESS_CAPABILITY_ALL; } } else if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) { @@ -1852,12 +1873,18 @@ public final class OomAdjuster { } } + // TOP process has all capabilities. + if (procState <= PROCESS_STATE_TOP) { + capability = PROCESS_CAPABILITY_ALL; + } + // Do final modification to adj. Everything we do between here and applying // the final setAdj must be done in this function, because we will also use // it when computing the final cached adj later. Note that we don't need to // worry about this for max adj above, since max adj will always be used to // keep it out of the cached vaues. app.curAdj = app.modifyRawOomAdj(adj); + app.curCapability = capability; app.setCurrentSchedulingGroup(schedGroup); app.setCurProcState(procState); app.setCurRawProcState(procState); @@ -1865,7 +1892,8 @@ public final class OomAdjuster { app.completedAdjSeq = mAdjSeq; // if curAdj or curProcState improved, then this process was promoted - return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState; + return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState + || app.curCapability != prevCapability ; } /** @@ -2175,6 +2203,11 @@ public final class OomAdjuster { maybeUpdateUsageStatsLocked(app, nowElapsed); } + if (app.curCapability != app.setCapability) { + changes |= ActivityManagerService.ProcessChangeItem.CHANGE_CAPABILITY; + app.setCapability = app.curCapability; + } + if (changes != 0) { if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Changes in " + app + ": " + changes); @@ -2182,12 +2215,13 @@ public final class OomAdjuster { mService.enqueueProcessChangeItemLocked(app.pid, app.info.uid); item.changes = changes; item.foregroundActivities = app.repForegroundActivities; + item.capability = app.setCapability; if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Item " + Integer.toHexString(System.identityHashCode(item)) + " " + app.toShortString() + ": changes=" + item.changes + " foreground=" + item.foregroundActivities + " type=" + app.adjType + " source=" + app.adjSource - + " target=" + app.adjTarget); + + " target=" + app.adjTarget + " capability=" + item.capability); } return success; diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 8163a6d3639f..f2f1e0286a58 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -810,9 +810,6 @@ public final class ProcessList { case ActivityManager.PROCESS_STATE_TOP: procState = "TOP "; break; - case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: - procState = "FGSL"; - break; case ActivityManager.PROCESS_STATE_BOUND_TOP: procState = "BTOP"; break; @@ -882,8 +879,6 @@ public final class ProcessList { return AppProtoEnums.PROCESS_STATE_PERSISTENT_UI; case ActivityManager.PROCESS_STATE_TOP: return AppProtoEnums.PROCESS_STATE_TOP; - case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: - return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE; case ActivityManager.PROCESS_STATE_BOUND_TOP: return AppProtoEnums.PROCESS_STATE_BOUND_TOP; case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE: @@ -1014,7 +1009,6 @@ public final class ProcessList { PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_TOP - PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_BOUND_TOP PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE @@ -2303,7 +2297,8 @@ public final class ProcessList { uidRec.updateHasInternetPermission(); mActiveUids.put(proc.uid, uidRec); EventLogTags.writeAmUidRunning(uidRec.uid); - mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState()); + mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(), + uidRec.curCapability); } proc.uidRecord = uidRec; @@ -2405,7 +2400,8 @@ public final class ProcessList { mService.enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE); EventLogTags.writeAmUidStopped(uid); mActiveUids.remove(uid); - mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT); + mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, + ActivityManager.PROCESS_CAPABILITY_NONE); } old.uidRecord = null; } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index bf43f3bffb17..1e0693f365e7 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -151,6 +151,9 @@ class ProcessRecord implements WindowProcessListener { int curAdj; // Current OOM adjustment for this process int setAdj; // Last set OOM adjustment for this process int verifiedAdj; // The last adjustment that was verified as actually being set + int curCapability; // Current capability flags of this process. For example, + // PROCESS_CAPABILITY_FOREGROUND_LOCATION is one capability. + int setCapability; // Last set capability flags. long lastCompactTime; // The last time that this process was compacted int reqCompactAction; // The most recent compaction action requested for this app. int lastCompactAction; // The most recent compaction action performed for this app. @@ -425,6 +428,8 @@ class ProcessRecord implements WindowProcessListener { pw.print(" mRepProcState="); pw.print(mRepProcState); pw.print(" pssProcState="); pw.print(pssProcState); pw.print(" setProcState="); pw.print(setProcState); + pw.print(" curCapability="); pw.print(curCapability); + pw.print(" setCapability="); pw.print(setCapability); pw.print(" lastStateTime="); TimeUtils.formatDuration(lastStateTime, nowUptime, pw); pw.println(); @@ -1097,6 +1102,10 @@ class ProcessRecord implements WindowProcessListener { && (mFgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0; } + boolean hasLocationCapability() { + return (setCapability & ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0; + } + int getForegroundServiceTypes() { return mHasForegroundServices ? mFgServiceTypes : 0; } diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java index 22a7de74cc38..e6cf2872a7e4 100644 --- a/services/core/java/com/android/server/am/UidRecord.java +++ b/services/core/java/com/android/server/am/UidRecord.java @@ -34,6 +34,8 @@ public final class UidRecord { final int uid; private int mCurProcState; int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT; + int curCapability; + int setCapability; long lastBackgroundTime; boolean ephemeral; boolean foregroundServices; @@ -108,6 +110,7 @@ public final class UidRecord { int uid; int change; int processState; + int capability; boolean ephemeral; long procStateSeq; } @@ -132,6 +135,8 @@ public final class UidRecord { public void reset() { setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY); foregroundServices = false; + curCapability = 0; + } public void updateHasInternetPermission() { diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index eecfdbded750..2e36a4305fad 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -16,6 +16,7 @@ package com.android.server.appop; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE; import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE; import static android.app.AppOpsManager.OP_CAMERA; @@ -27,7 +28,6 @@ import static android.app.AppOpsManager.UID_STATE_BACKGROUND; import static android.app.AppOpsManager.UID_STATE_CACHED; import static android.app.AppOpsManager.UID_STATE_FOREGROUND; import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE; -import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION; import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED; import static android.app.AppOpsManager.UID_STATE_PERSISTENT; import static android.app.AppOpsManager.UID_STATE_TOP; @@ -119,12 +119,6 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.LockGuard; -import libcore.util.EmptyArray; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -144,6 +138,12 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import libcore.util.EmptyArray; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + public class AppOpsService extends IAppOpsService.Stub { static final String TAG = "AppOps"; static final boolean DEBUG = false; @@ -164,12 +164,10 @@ public class AppOpsService extends IAppOpsService.Stub { UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP - UID_STATE_FOREGROUND_SERVICE_LOCATION, - // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE - UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND + UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP @@ -364,7 +362,8 @@ public class AppOpsService extends IAppOpsService.Stub { public int state = UID_STATE_CACHED; public int pendingState = UID_STATE_CACHED; public long pendingStateCommitTime; - + public int capability; + public int pendingCapability; // For all features combined public int startNesting; @@ -393,8 +392,25 @@ public class AppOpsService extends IAppOpsService.Stub { int evalMode(int op, int mode) { if (mode == AppOpsManager.MODE_FOREGROUND) { - return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op) - ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; + if (state <= UID_STATE_TOP) { + // process is in foreground. + return AppOpsManager.MODE_ALLOWED; + } else if (state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)) { + // process is in foreground, check its capability. + switch (op) { + case AppOpsManager.OP_FINE_LOCATION: + case AppOpsManager.OP_COARSE_LOCATION: + case AppOpsManager.OP_MONITOR_LOCATION: + case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION: + return ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) + ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; + default: + return AppOpsManager.MODE_ALLOWED; + } + } else { + // process is not in foreground. + return AppOpsManager.MODE_IGNORED; + } } return mode; } @@ -1062,13 +1078,16 @@ public class AppOpsService extends IAppOpsService.Stub { } } - public void updateUidProcState(int uid, int procState) { + public void updateUidProcState(int uid, int procState, + @ActivityManager.ProcessCapability int capability) { synchronized (this) { final UidState uidState = getUidStateLocked(uid, true); - int newState = PROCESS_STATE_TO_UID_STATE[procState]; - if (uidState != null && uidState.pendingState != newState) { + final int newState = PROCESS_STATE_TO_UID_STATE[procState]; + if (uidState != null && (uidState.pendingState != newState + || uidState.pendingCapability != capability)) { final int oldPendingState = uidState.pendingState; uidState.pendingState = newState; + uidState.pendingCapability = capability; if (newState < uidState.state || (newState <= UID_STATE_MAX_LAST_NON_RESTRICTED && uidState.state > UID_STATE_MAX_LAST_NON_RESTRICTED)) { @@ -1076,6 +1095,9 @@ public class AppOpsService extends IAppOpsService.Stub { // foreground and the old state is in the background, then always do it // immediately. commitUidPendingStateLocked(uidState); + } else if (newState == uidState.state && capability != uidState.capability) { + // No change on process state, but process capability has changed. + commitUidPendingStateLocked(uidState); } else if (uidState.pendingStateCommitTime == 0) { // We are moving to a less important state for the first time, // delay the application for a bit. @@ -2857,6 +2879,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } uidState.state = uidState.pendingState; + uidState.capability = uidState.pendingCapability; uidState.pendingStateCommitTime = 0; } @@ -4494,6 +4517,12 @@ public class AppOpsService extends IAppOpsService.Stub { pw.print(" pendingState="); pw.println(AppOpsManager.getUidStateName(uidState.pendingState)); } + pw.print(" capability="); + pw.println(uidState.capability); + if (uidState.capability != uidState.pendingCapability) { + pw.print(" pendingCapability="); + pw.println(uidState.pendingCapability); + } if (uidState.pendingStateCommitTime != 0) { pw.print(" pendingStateCommitTime="); TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw); diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING index e9d2b312e01c..9c03a3606e6c 100644 --- a/services/core/java/com/android/server/appop/TEST_MAPPING +++ b/services/core/java/com/android/server/appop/TEST_MAPPING @@ -35,6 +35,9 @@ "include-filter": "android.permission.cts.SharedUidPermissionsTest" } ] + }, + { + "name": "CtsAppTestCases:ActivityManagerApi29Test" } ] } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 0d493b825133..4feaeae02aeb 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -580,7 +580,8 @@ public class AudioService extends IAudioService.Stub } final private IUidObserver mUidObserver = new IUidObserver.Stub() { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { + @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, + int capability) { } @Override public void onUidGone(int uid, boolean disabled) { diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index bc5973d1b270..87624359ef85 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.compat.annotation.EnabledAfter; import android.content.pm.ApplicationInfo; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.compat.config.Change; import java.util.HashMap; @@ -35,12 +36,8 @@ import java.util.Map; * * <p>Note, this class is not thread safe so callers must ensure thread safety. */ -public final class CompatChange { +public final class CompatChange extends CompatibilityChangeInfo { - private final long mChangeId; - @Nullable private final String mName; - private final int mEnableAfterTargetSdk; - private final boolean mDisabled; private Map<String, Boolean> mPackageOverrides; public CompatChange(long changeId) { @@ -56,29 +53,15 @@ public final class CompatChange { */ public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk, boolean disabled) { - mChangeId = changeId; - mName = name; - mEnableAfterTargetSdk = enableAfterTargetSdk; - mDisabled = disabled; + super(changeId, name, enableAfterTargetSdk, disabled); } /** * @param change an object generated by services/core/xsd/platform-compat-config.xsd */ public CompatChange(Change change) { - mChangeId = change.getId(); - mName = change.getName(); - mEnableAfterTargetSdk = change.getEnableAfterTargetSdk(); - mDisabled = change.getDisabled(); - } - - long getId() { - return mChangeId; - } - - @Nullable - String getName() { - return mName; + super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(), + change.getDisabled()); } /** @@ -121,11 +104,11 @@ public final class CompatChange { if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) { return mPackageOverrides.get(app.packageName); } - if (mDisabled) { + if (getDisabled()) { return false; } - if (mEnableAfterTargetSdk != -1) { - return app.targetSdkVersion > mEnableAfterTargetSdk; + if (getEnableAfterTargetSdk() != -1) { + return app.targetSdkVersion > getEnableAfterTargetSdk(); } return true; } @@ -133,14 +116,14 @@ public final class CompatChange { @Override public String toString() { StringBuilder sb = new StringBuilder("ChangeId(") - .append(mChangeId); - if (mName != null) { - sb.append("; name=").append(mName); + .append(getId()); + if (getName() != null) { + sb.append("; name=").append(getName()); } - if (mEnableAfterTargetSdk != -1) { - sb.append("; enableAfterTargetSdk=").append(mEnableAfterTargetSdk); + if (getEnableAfterTargetSdk() != -1) { + sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk()); } - if (mDisabled) { + if (getDisabled()) { sb.append("; disabled"); } if (mPackageOverrides != null && mPackageOverrides.size() > 0) { diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 0fabd9aef373..d6ec22b078ea 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -16,6 +16,7 @@ package com.android.server.compat; +import android.compat.Compatibility.ChangeConfig; import android.content.pm.ApplicationInfo; import android.os.Environment; import android.text.TextUtils; @@ -26,6 +27,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.compat.config.Change; import com.android.server.compat.config.XmlParser; @@ -37,6 +39,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; import javax.xml.datatype.DatatypeConfigurationException; /** @@ -243,6 +247,49 @@ public final class CompatConfig { } } + /** + * Get the config for a given app. + * + * @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped. + * @return A {@link CompatibilityChangeConfig} which contains the compat config info for the + * given app. + */ + + public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) { + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + synchronized (mChanges) { + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange c = mChanges.valueAt(i); + if (c.isEnabled(applicationInfo)) { + enabled.add(c.getId()); + } else { + disabled.add(c.getId()); + } + } + } + return new CompatibilityChangeConfig(new ChangeConfig(enabled, disabled)); + } + + /** + * Dumps all the compatibility change information. + * + * @return An array of {@link CompatibilityChangeInfo} with the current changes. + */ + public CompatibilityChangeInfo[] dumpChanges() { + synchronized (mChanges) { + CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()]; + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange change = mChanges.valueAt(i); + changeInfos[i] = new CompatibilityChangeInfo(change.getId(), + change.getName(), + change.getEnableAfterTargetSdk(), + change.getDisabled()); + } + return changeInfos; + } + } + CompatConfig initConfigFromLib(File libraryDir) { if (!libraryDir.exists() || !libraryDir.isDirectory()) { Slog.e(TAG, "No directory " + libraryDir + ", skipping"); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 9ac9955493cc..75e2d220898d 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -25,6 +25,7 @@ import android.util.StatsLog; import com.android.internal.compat.ChangeReporter; import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.internal.compat.IPlatformCompat; import com.android.internal.util.DumpUtils; @@ -114,6 +115,16 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { + return CompatConfig.get().getAppConfig(appInfo); + } + + @Override + public CompatibilityChangeInfo[] listAllChanges() { + return CompatConfig.get().dumpChanges(); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; CompatConfig.get().dumpConfig(pw); diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 362955d589af..2c23c51216a8 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -1810,8 +1810,9 @@ public class InputManagerService extends IInputManager.Stub } // Native callback. - private long notifyANR(IBinder token, String reason) { - return mWindowManagerCallbacks.notifyANR( + private long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token, + String reason) { + return mWindowManagerCallbacks.notifyANR(inputApplicationHandle, token, reason); } @@ -2055,7 +2056,12 @@ public class InputManagerService extends IInputManager.Stub public void notifyInputChannelBroken(IBinder token); - public long notifyANR(IBinder token, String reason); + /** + * Notifies the window manager about an application that is not responding. + * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. + */ + long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token, + String reason); public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags); diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java new file mode 100644 index 000000000000..c1567bc51474 --- /dev/null +++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 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.integrity.parser; + +import com.android.server.integrity.model.Rule; + +import java.io.InputStream; + +/** A helper class to parse rules into the {@link Rule} model from Binary representation. */ +public class RuleBinaryParser implements RuleParser { + + @Override + public Rule parse(String ruleText) { + // TODO: Implement binary text parser. + return null; + } + + @Override + public Rule parse(InputStream inputStream) { + // TODO: Implement stream parser. + return null; + } +} diff --git a/services/core/java/com/android/server/integrity/parser/RuleParser.java b/services/core/java/com/android/server/integrity/parser/RuleParser.java new file mode 100644 index 000000000000..96ed5993cb06 --- /dev/null +++ b/services/core/java/com/android/server/integrity/parser/RuleParser.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 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.integrity.parser; + +import com.android.server.integrity.model.Rule; + +import java.io.InputStream; + +/** A helper class to parse rules into the {@link Rule} model. */ +public interface RuleParser { + + /** Parse rules from a string. */ + Rule parse(String ruleText); + + /** Parse rules from an input stream. */ + Rule parse(InputStream inputStream); +} diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java new file mode 100644 index 000000000000..8b1bec90f994 --- /dev/null +++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 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.integrity.parser; + +import com.android.server.integrity.model.Rule; + +import java.io.InputStream; + +/** A helper class to parse rules into the {@link Rule} model from Xml representation. */ +public final class RuleXmlParser implements RuleParser { + + @Override + public Rule parse(String ruleText) { + // TODO: Implement text parser. + return null; + } + + @Override + public Rule parse(InputStream inputStream) { + // TODO: Implement stream parser. + return null; + } +} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java new file mode 100644 index 000000000000..ecb00a4b7025 --- /dev/null +++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 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.integrity.serializer; + +import com.android.server.integrity.model.Rule; + +import java.io.OutputStream; + +/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */ +public class RuleBinarySerializer implements RuleSerializer { + + @Override + public void serialize(Rule rule, OutputStream outputStream) { + // TODO: Implement stream serializer. + } + + @Override + public String serialize(Rule rule) { + // TODO: Implement text serializer. + return null; + } +} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java new file mode 100644 index 000000000000..07a912f8aeab --- /dev/null +++ b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 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.integrity.serializer; + +import com.android.server.integrity.model.Rule; + +import java.io.OutputStream; + +/** A helper class to serialize rules from the {@link Rule} model. */ +public interface RuleSerializer { + + /** Serialize a rule to an output stream */ + void serialize(Rule rule, OutputStream outputStream); + + /** Serialize a rule to a string. */ + String serialize(Rule rule); +} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java new file mode 100644 index 000000000000..62973e2b026f --- /dev/null +++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 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.integrity.serializer; + +import com.android.server.integrity.model.Rule; + +import java.io.OutputStream; + +/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */ +public class RuleXmlSerializer implements RuleSerializer { + + @Override + public void serialize(Rule rule, OutputStream outputStream) { + // TODO: Implement stream serializer. + } + + @Override + public String serialize(Rule rule) { + // TODO: Implement text serializer. + return null; + } +} diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 388214bffcb2..32d4b726f011 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -912,7 +912,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } final private IUidObserver mUidObserver = new IUidObserver.Stub() { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { + @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, + int capability) { mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, uid, procState, procStateSeq).sendToTarget(); } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 8253b392768f..f0a1c70057c4 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -495,7 +495,7 @@ public class ShortcutService extends IShortcutService.Stub { final private IUidObserver mUidObserver = new IUidObserver.Stub() { @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) { + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { injectPostToHandler(() -> handleOnUidStateChanged(uid, procState)); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index fe371250ac17..5c9b9c93e4fe 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1593,6 +1593,7 @@ public class UserManagerService extends IUserManager.Stub { /** @return a specific user restriction that's in effect currently. */ @Override public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) { + checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "hasUserRestriction"); return mLocalService.hasUserRestriction(restrictionKey, userId); } @@ -1717,6 +1718,7 @@ public class UserManagerService extends IUserManager.Stub { */ @Override public Bundle getUserRestrictions(@UserIdInt int userId) { + checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserRestrictions"); return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId)); } 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 f56231fc02af..41dcaa59047b 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -16,8 +16,6 @@ package com.android.server.pm.dex; -import static android.provider.DeviceConfig.NAMESPACE_DEX_BOOT; - import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo; import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo; @@ -31,7 +29,6 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; -import android.provider.DeviceConfig; import android.util.Log; import android.util.Slog; import android.util.jar.StrictJarFile; @@ -72,10 +69,6 @@ public class DexManager { private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST = "pm.dexopt.priv-apps-oob-list"; - // flags for Device Config API - private static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled"; - private static final String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Context mContext; @@ -717,24 +710,16 @@ public class DexManager { return isPackageSelectedToRunOobInternal( SystemProperties.getBoolean(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB, false), SystemProperties.get(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST, "ALL"), - DeviceConfig.getProperty(NAMESPACE_DEX_BOOT, PRIV_APPS_OOB_ENABLED), - DeviceConfig.getProperty(NAMESPACE_DEX_BOOT, PRIV_APPS_OOB_WHITELIST), packageNamesInSameProcess); } @VisibleForTesting - /* package */ static boolean isPackageSelectedToRunOobInternal( - boolean isDefaultEnabled, String defaultWhitelist, String overrideEnabled, - String overrideWhitelist, Collection<String> packageNamesInSameProcess) { - // Allow experiment (if exists) to override device configuration. - boolean enabled = overrideEnabled != null ? overrideEnabled.equals("true") - : isDefaultEnabled; - if (!enabled) { + /* package */ static boolean isPackageSelectedToRunOobInternal(boolean isEnabled, + String whitelist, Collection<String> packageNamesInSameProcess) { + if (!isEnabled) { return false; } - // Similarly, experiment flag can override the whitelist. - String whitelist = overrideWhitelist != null ? overrideWhitelist : defaultWhitelist; if ("ALL".equals(whitelist)) { return true; } diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java index 852f70779f77..cb0b45ceaf05 100644 --- a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java +++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java @@ -18,6 +18,7 @@ package com.android.server.updates; import android.content.Context; import android.content.Intent; +import android.telephony.TelephonyManager; import android.util.Slog; /** @@ -34,6 +35,11 @@ public class EmergencyNumberDbInstallReceiver extends ConfigUpdateInstallReceive @Override protected void postInstall(Context context, Intent intent) { Slog.i(TAG, "Emergency number database is updated in file partition"); - // TODO Send a notification to EmergencyNumberTracker for updating of emergency number db. + + // Notify EmergencyNumberTracker for emergency number installation complete. + Intent notifyInstallComplete = new Intent( + TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED); + context.sendBroadcast( + notifyInstallComplete, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); } } diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 5e4f75cca10d..c57ac11723b4 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -132,17 +132,20 @@ final class AccessibilityController { return false; } - if (mWindowsForAccessibilityObserver.get(displayId) != null) { - final Display display = dc.getDisplay(); - if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) { - // The window observer of this embedded display had been set from - // window manager after setting its parent window. - return false; - } else { - throw new IllegalStateException( - "Windows for accessibility callback of display " - + displayId + " already set!"); + final Display display = dc.getDisplay(); + if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) { + // If this display is an embedded one, its window observer should have been set from + // window manager after setting its parent window. But if its window observer is + // empty, that means this mapping didn't be set, and needs to do this again. + // This happened when accessibility window observer is disabled and enabled again. + if (mWindowsForAccessibilityObserver.get(displayId) == null) { + handleWindowObserverOfEmbeddedDisplayLocked(displayId, dc.getParentWindow()); } + return false; + } else if (mWindowsForAccessibilityObserver.get(displayId) != null) { + throw new IllegalStateException( + "Windows for accessibility callback of display " + + displayId + " already set!"); } mWindowsForAccessibilityObserver.put(displayId, new WindowsForAccessibilityObserver(mService, displayId, callback)); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 933df1ea1411..76ac5392fa76 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -179,7 +179,7 @@ import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT; import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS; import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED; import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW; -import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING; +import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING; import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START; import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN; import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING; @@ -205,16 +205,17 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.wm.TaskPersister.DEBUG; import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; -import static com.android.server.wm.WindowManagerService.logWithStack; import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; -import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; @@ -291,16 +292,17 @@ import android.view.IApplicationToken; import android.view.InputApplicationHandle; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationDefinition; +import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; -import com.android.internal.R; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.XmlUtils; import com.android.server.AttributeCache; @@ -315,6 +317,7 @@ import com.android.server.uri.UriPermissionOwner; import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot; import com.android.server.wm.ActivityStack.ActivityState; import com.android.server.wm.WindowManagerService.H; +import com.android.server.wm.utils.InsetUtils; import com.google.android.collect.Sets; @@ -332,7 +335,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.function.Consumer; /** * An entry in the history stack, representing an activity. @@ -374,6 +376,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k. */ @VisibleForTesting static final int Z_BOOST_BASE = 800570000; + static final int INVALID_PID = -1; final ActivityTaskManagerService mAtmService; final ActivityInfo info; // activity info provided by developer in AndroidManifest @@ -551,24 +554,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean mCurrentLaunchCanTurnScreenOn = true; /** - * This gets used during some open/close transitions as well as during a change transition - * where it represents the starting-state snapshot. - */ - private AppWindowThumbnail mThumbnail; - private final Rect mTransitStartRect = new Rect(); - - /** - * If we are running an animation, this determines the transition type. Must be one of - * AppTransition.TRANSIT_* constants. - */ - private int mTransit; - - /** - * If we are running an animation, this determines the flags during this animation. Must be a - * bitwise combination of AppTransition.TRANSIT_FLAG_* constants. - */ - private int mTransitFlags; - /** * This leash is used to "freeze" the app surface in place after the state change, but before * the animation is ready to start. */ @@ -664,7 +649,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // TODO: Have a WindowContainer state for tracking exiting/deferred removal. boolean mIsExiting; - boolean mLaunchTaskBehind; boolean mEnteringAnimation; boolean mAppStopped; @@ -676,15 +660,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>(); - /** Whether this token should be boosted at the top of all app window tokens. */ - @VisibleForTesting boolean mNeedsZBoost; - - /** Layer used to constrain the animation to a token's stack bounds. */ - SurfaceControl mAnimationBoundsLayer; - - /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */ - boolean mNeedsAnimationBoundsLayer; - private AppSaturationInfo mLastAppSaturationInfo; private final ColorDisplayService.ColorTransformController mColorTransformController = @@ -710,10 +685,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private final Configuration mTmpConfig = new Configuration(); private final Rect mTmpBounds = new Rect(); - private final Point mTmpPoint = new Point(); - private final Rect mTmpRect = new Rect(); - private final Rect mTmpPrevBounds = new Rect(); - // Token for targeting this activity for assist purposes. final Binder assistToken = new Binder(); @@ -2305,7 +2276,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * 2. App is delayed closing since it might enter PIP. */ boolean isClosingOrEnteringPip() { - return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip; + return (isAnimating(TRANSITION | PARENTS) && hiddenRequested) || mWillCloseOrEnterPip; } /** * @return Whether AppOps allows this package to enter picture-in-picture. @@ -3114,7 +3085,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app %s delayed=%b animation=%s animating=%b", this, delayed, - getAnimation(), isSelfAnimating()); + getAnimation(), isAnimating(TRANSITION)); ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s" + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4)); @@ -3126,7 +3097,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // If this window was animating, then we need to ensure that the app transition notifies // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(), // so add to that list now - if (isSelfAnimating()) { + if (isAnimating(TRANSITION)) { getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token); } @@ -3474,7 +3445,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * color mode set to avoid jank in the middle of the transition. */ boolean canShowWindows() { - return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow()); + return allDrawn && !(isAnimating() && hasNonDefaultColorWindow()); } /** @@ -3536,17 +3507,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return forAllWindowsUnchecked(callback, traverseTopToBottom); } - @Override - void forAllActivities(Consumer<ActivityRecord> callback) { - callback.accept(this); - } - boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { return super.forAllWindows(callback, traverseTopToBottom); } @Override + boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) { + return callback.apply(this); + } + + @Override protected void setLayer(Transaction t, int layer) { if (!mSurfaceAnimator.hasLeash()) { t.setLayer(mSurfaceControl, layer); @@ -4127,8 +4098,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (transit != WindowManager.TRANSIT_UNSET) { if (mUseTransferredAnimation) { - runningAppAnimation = isReallyAnimating(); - } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) { + runningAppAnimation = isAnimating(); + } else if (applyAnimation(lp, transit, visible, isVoiceInteraction)) { runningAppAnimation = true; } delayed = runningAppAnimation; @@ -4179,21 +4150,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } mUseTransferredAnimation = false; - if (isReallyAnimating()) { - delayed = true; - } else { + delayed = isAnimating(CHILDREN); + if (!delayed) { // We aren't animating anything, but exiting windows rely on the animation finished // callback being called in case the ActivityRecord was pretending to be animating, // which we might have done because we were in closing/opening apps list. onAnimationFinished(); } - for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) { - if ((mChildren.get(i)).isSelfOrChildAnimating()) { - delayed = true; - } - } - if (visibilityChanged) { if (visible && !delayed) { // The token was made immediately visible, there will be no entrance animation. @@ -4208,7 +4172,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // updated. // If we're becoming invisible, update the client visibility if we are not running an // animation. Otherwise, we'll update client visibility in onAnimationFinished. - if (visible || !isReallyAnimating()) { + if (visible || !isAnimating()) { setClientHidden(!visible); } @@ -5288,13 +5252,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (!allDrawn && w.mightAffectAllDrawn()) { if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) { Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() - + ", isAnimationSet=" + isSelfAnimating()); + + ", isAnimationSet=" + isAnimating(TRANSITION)); if (!w.isDrawnLw()) { Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController + " pv=" + w.isVisibleByPolicy() + " mDrawState=" + winAnimator.drawStateToString() + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested - + " a=" + isSelfAnimating()); + + " a=" + isAnimating(TRANSITION)); } } @@ -5350,7 +5314,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A anrActivity = getWaitingHistoryRecordLocked(); anrApp = app; windowFromSameProcessAsActivity = - !hasProcess() || app.getPid() == windowPid || windowPid == -1; + !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID; } if (windowFromSameProcessAsActivity) { @@ -5722,204 +5686,55 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - @VisibleForTesting boolean shouldAnimate(int transit) { + final Task task = getTask(); + if (task != null && !task.shouldAnimate()) { + return false; + } final boolean isSplitScreenPrimary = getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN; - // Don't animate while the task runs recents animation but only if we are in the mode - // where we cancel with deferred screenshot, which means that the controller has - // transformed the task. - final RecentsAnimationController controller = mWmService.getRecentsAnimationController(); - if (controller != null && controller.isAnimatingTask(getTask()) - && controller.shouldDeferCancelUntilNextTransition()) { - return false; - } - // We animate always if it's not split screen primary, and only some special cases in split // screen primary because it causes issues with stack clipping when we run an un-minimize // animation at the same time. return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation; } - /** - * Creates a layer to apply crop to an animation. - */ - private SurfaceControl createAnimationBoundsLayer(Transaction t) { - ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer"); - final SurfaceControl.Builder builder = makeAnimationLeash() - .setParent(getAnimationLeashParent()) - .setName(getSurfaceControl() + " - animation-bounds"); - final SurfaceControl boundsLayer = builder.build(); - t.show(boundsLayer); - return boundsLayer; + @Override + boolean isChangingAppTransition() { + final Task task = getTask(); + if (task != null) { + return task.isChangingAppTransition(); + } + return super.isChangingAppTransition(); } - boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter, + @Override + boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { - if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: transition animation is disabled or skipped. " - + "atoken=%s", this); + + "container=%s", this); cancelAnimation(); return false; } - - // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason - // to animate and it can cause strange artifacts when we unfreeze the display if some - // different animation is running. - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked"); - if (okToAnimate()) { - final AnimationAdapter adapter; - AnimationAdapter thumbnailAdapter = null; - - final int appStackClipMode = - getDisplayContent().mAppTransition.getAppStackClipMode(); - - // Separate position and size for use in animators. - mTmpRect.set(getAnimationBounds(appStackClipMode)); - mTmpPoint.set(mTmpRect.left, mTmpRect.top); - mTmpRect.offsetTo(0, 0); - - final boolean isChanging = AppTransition.isChangeTransit(transit) && enter - && getDisplayContent().mChangingApps.contains(this); - - // Delaying animation start isn't compatible with remote animations at all. - if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null - && !mSurfaceAnimator.isAnimationStartDelayed()) { - RemoteAnimationController.RemoteAnimationRecord adapters = - getDisplayContent().mAppTransition.getRemoteAnimationController() - .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect, - (isChanging ? mTransitStartRect : null)); - adapter = adapters.mAdapter; - thumbnailAdapter = adapters.mThumbnailAdapter; - } else if (isChanging) { - final float durationScale = mWmService.getTransitionAnimationScaleLocked(); - mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y); - adapter = new LocalAnimationAdapter( - new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, - getDisplayContent().getDisplayInfo(), durationScale, - true /* isAppAnimation */, false /* isThumbnail */), - mWmService.mSurfaceAnimationRunner); - if (mThumbnail != null) { - thumbnailAdapter = new LocalAnimationAdapter( - new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, - getDisplayContent().getDisplayInfo(), durationScale, - true /* isAppAnimation */, true /* isThumbnail */), - mWmService.mSurfaceAnimationRunner); - } - mTransit = transit; - mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags(); - } else { - mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM); - - final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction); - if (a != null) { - // Only apply corner radius to animation if we're not in multi window mode. - // We don't want rounded corners when in pip or split screen. - final float windowCornerRadius = !inMultiWindowMode() - ? getDisplayContent().getWindowCornerRadius() - : 0; - adapter = new LocalAnimationAdapter( - new WindowAnimationSpec(a, mTmpPoint, mTmpRect, - getDisplayContent().mAppTransition.canSkipFirstFrame(), - appStackClipMode, - true /* isAppAnimation */, - windowCornerRadius), - mWmService.mSurfaceAnimationRunner); - if (a.getZAdjustment() == Animation.ZORDER_TOP) { - mNeedsZBoost = true; - } - mTransit = transit; - mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags(); - } else { - adapter = null; - } - } - if (adapter != null) { - startAnimation(getPendingTransaction(), adapter, !isVisible()); - if (adapter.getShowWallpaper()) { - mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; - } - if (thumbnailAdapter != null) { - mThumbnail.startAnimation( - getPendingTransaction(), thumbnailAdapter, !isVisible()); - } - } - } else { - cancelAnimation(); - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - - return isReallyAnimating(); + return super.applyAnimation(lp, transit, enter, isVoiceInteraction); } - private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, - boolean isVoiceInteraction) { - final DisplayContent displayContent = getTask().getDisplayContent(); - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - final int width = displayInfo.appWidth; - final int height = displayInfo.appHeight; - ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, - "applyAnimation: atoken=%s", this); - - // Determine the visible rect to calculate the thumbnail clip - final WindowState win = findMainWindow(); - final Rect frame = new Rect(0, 0, width, height); - final Rect displayFrame = new Rect(0, 0, - displayInfo.logicalWidth, displayInfo.logicalHeight); - final Rect insets = new Rect(); - final Rect stableInsets = new Rect(); - Rect surfaceInsets = null; - final boolean freeform = win != null && win.inFreeformWindowingMode(); - if (win != null) { - // Containing frame will usually cover the whole screen, including dialog windows. - // For freeform workspace windows it will not cover the whole screen and it also - // won't exactly match the final freeform window frame (e.g. when overlapping with - // the status bar). In that case we need to use the final frame. - if (freeform) { - frame.set(win.getFrameLw()); - } else if (win.isLetterboxedAppWindow()) { - frame.set(getTask().getBounds()); - } else if (win.isDockedResizing()) { - // If we are animating while docked resizing, then use the stack bounds as the - // animation target (which will be different than the task bounds) - frame.set(getTask().getParent().getBounds()); - } else { - frame.set(win.getContainingFrame()); - } - surfaceInsets = win.getAttrs().surfaceInsets; - // XXX(b/72757033): These are insets relative to the window frame, but we're really - // interested in the insets relative to the frame we chose in the if-blocks above. - win.getContentInsets(insets); - win.getStableInsets(stableInsets); - } - - if (mLaunchTaskBehind) { - // Differentiate the two animations. This one which is briefly on the screen - // gets the !enter animation, and the other activity which remains on the - // screen gets the enter animation. Both appear in the mOpeningApps set. - enter = false; - } - ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, - "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s " - + "surfaceInsets=%s", - AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets); - final Configuration displayConfig = displayContent.getConfiguration(); - final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter, - displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets, - surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId); - if (a != null) { - if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this); - final int containingWidth = frame.width(); - final int containingHeight = frame.height(); - a.initialize(containingWidth, containingHeight, width, height); - a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked()); - } - return a; + /** + * Creates a layer to apply crop to an animation. + */ + private SurfaceControl createAnimationBoundsLayer(Transaction t) { + ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer"); + final SurfaceControl.Builder builder = makeAnimationLeash() + .setParent(getAnimationLeashParent()) + .setName(getSurfaceControl() + " - animation-bounds"); + final SurfaceControl boundsLayer = builder.build(); + t.show(boundsLayer); + return boundsLayer; } @Override @@ -5941,6 +5756,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM); } + @Override boolean isWaitingForTransitionStart() { final DisplayContent dc = getDisplayContent(); // TODO: Test for null can be removed once unification is done. @@ -6069,10 +5885,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void prepareSurfaces() { - // isSelfAnimating also returns true when we are about to start a transition, so we need - // to check super here. - final boolean reallyAnimating = super.isSelfAnimating(); - final boolean show = !isHidden() || reallyAnimating; + final boolean show = !isHidden() || isAnimating(); if (mSurfaceControl != null) { if (show && !mLastSurfaceShowing) { @@ -6100,14 +5913,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void attachThumbnailAnimation() { - if (!isReallyAnimating()) { + if (!isAnimating()) { return; } - final int taskId = getTask().mTaskId; final GraphicBuffer thumbnailHeader = - getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId); + getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(getTask()); if (thumbnailHeader == null) { - ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId); + ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", getTask()); return; } clearThumbnail(); @@ -6121,7 +5933,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation. */ void attachCrossProfileAppsThumbnailAnimation() { - if (!isReallyAnimating()) { + if (!isAnimating()) { return; } clearThumbnail(); @@ -6161,22 +5973,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final Rect insets = win != null ? win.getContentInsets() : null; final Configuration displayConfig = mDisplayContent.getConfiguration(); return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked( - appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode, + appRect, insets, thumbnailHeader, getTask(), displayConfig.uiMode, displayConfig.orientation); } @Override - boolean isAppAnimating() { - return isSelfAnimating(); - } - - @Override - boolean isSelfAnimating() { - // If we are about to start a transition, we also need to be considered animating. - return isWaitingForTransitionStart() || isReallyAnimating(); - } - - @Override public void onAnimationLeashLost(Transaction t) { super.onAnimationLeashLost(t); if (mAnimationBoundsLayer != null) { @@ -6281,15 +6082,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - /** - * @return True if and only if we are actually running an animation. Note that - * {@link #isSelfAnimating} also returns true if we are waiting for an animation to - * start. - */ - private boolean isReallyAnimating() { - return super.isSelfAnimating(); - } - @Override void cancelAnimation() { cancelAnimationOnly(); @@ -6691,6 +6483,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } @VisibleForTesting + @Override Rect getAnimationBounds(int appStackClipMode) { if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) { // Using the stack bounds here effectively applies the clipping before animation. @@ -7643,7 +7436,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A super.writeToProto(proto, WINDOW_TOKEN, logLevel); proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing); proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart()); - proto.write(IS_REALLY_ANIMATING, isReallyAnimating()); + proto.write(IS_ANIMATING, isAnimating()); if (mThumbnail != null){ mThumbnail.writeToProto(proto, THUMBNAIL); } @@ -7765,4 +7558,35 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length); } } + + @Override + RemoteAnimationTarget createRemoteAnimationTarget( + RemoteAnimationController.RemoteAnimationRecord record) { + final Task task = getTask(); + final WindowState mainWindow = findMainWindow(); + if (task == null || mainWindow == null) { + return null; + } + final Rect insets = new Rect(); + mainWindow.getContentInsets(insets); + InsetUtils.addInsets(insets, getLetterboxInsets()); + return new RemoteAnimationTarget(task.mTaskId, record.getMode(), + record.mAdapter.mCapturedLeash, !task.fillsParent(), + mainWindow.mWinAnimator.mLastClipRect, insets, + getPrefixOrderIndex(), record.mAdapter.mPosition, + record.mAdapter.mStackBounds, task.getWindowConfiguration(), + false /*isNotInRecents*/, + record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null, + record.mStartBounds); + } + + @Override + void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, + Rect outSurfaceInsets) { + final WindowState win = findMainWindow(); + if (win == null) { + return; + } + win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); + } } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index b4b95cc8a273..dc3d2631a5d7 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -82,6 +82,7 @@ import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import android.Manifest; import android.app.Activity; @@ -2132,7 +2133,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); - final boolean animating = s.isSelfAnimating(); + final boolean animating = s.isAnimating(TRANSITION); if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " animating=" + animating + " finishing=" + s.finishing); diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index c1143c856bb4..cb9a200e6010 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -219,7 +219,7 @@ public class AppTransition implements Dump { private int mNextAppTransitionExit; private int mNextAppTransitionInPlace; - // Keyed by task id. + // Keyed by WindowContainer hashCode. private final SparseArray<AppTransitionAnimationSpec> mNextAppTransitionAnimationsSpecs = new SparseArray<>(); private IAppTransitionAnimationSpecsFuture mNextAppTransitionAnimationsSpecsFuture; @@ -372,8 +372,9 @@ public class AppTransition implements Dump { setAppTransitionState(APP_STATE_TIMEOUT); } - GraphicBuffer getAppTransitionThumbnailHeader(int taskId) { - AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId); + GraphicBuffer getAppTransitionThumbnailHeader(WindowContainer container) { + AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get( + container.hashCode()); if (spec == null) { spec = mDefaultNextAppTransitionAnimationSpec; } @@ -789,14 +790,15 @@ public class AppTransition implements Dump { } } - void getNextAppTransitionStartRect(int taskId, Rect rect) { - AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId); + void getNextAppTransitionStartRect(WindowContainer container, Rect rect) { + AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get( + container.hashCode()); if (spec == null) { spec = mDefaultNextAppTransitionAnimationSpec; } if (spec == null || spec.rect == null) { - Slog.e(TAG, "Starting rect for task: " + taskId + " requested, but not available", - new Throwable()); + Slog.e(TAG, "Starting rect for container: " + container + + " requested, but not available", new Throwable()); rect.setEmpty(); } else { rect.set(spec.rect); @@ -1065,7 +1067,7 @@ public class AppTransition implements Dump { * when a thumbnail is specified with the pending animation override. */ Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets, - GraphicBuffer thumbnailHeader, final int taskId, int uiMode, int orientation) { + GraphicBuffer thumbnailHeader, WindowContainer container, int uiMode, int orientation) { Animation a; final int thumbWidthI = thumbnailHeader.getWidth(); final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; @@ -1073,7 +1075,7 @@ public class AppTransition implements Dump { final int appWidth = appRect.width(); float scaleW = appWidth / thumbWidth; - getNextAppTransitionStartRect(taskId, mTmpRect); + getNextAppTransitionStartRect(container, mTmpRect); final float fromX; float fromY; final float toX; @@ -1226,7 +1228,7 @@ public class AppTransition implements Dump { Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState, int uiMode, int orientation, int transit, Rect containingFrame, Rect contentInsets, @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean freeform, - int taskId) { + WindowContainer container) { Animation a; final int appWidth = containingFrame.width(); final int appHeight = containingFrame.height(); @@ -1244,10 +1246,10 @@ public class AppTransition implements Dump { final boolean scaleUp = thumbTransitState == THUMBNAIL_TRANSITION_ENTER_SCALE_UP; if (freeform && scaleUp) { a = createAspectScaledThumbnailEnterFreeformAnimationLocked( - containingFrame, surfaceInsets, taskId); + containingFrame, surfaceInsets, container); } else if (freeform) { a = createAspectScaledThumbnailExitFreeformAnimationLocked( - containingFrame, surfaceInsets, taskId); + containingFrame, surfaceInsets, container); } else { AnimationSet set = new AnimationSet(true); @@ -1359,15 +1361,15 @@ public class AppTransition implements Dump { } private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame, - @Nullable Rect surfaceInsets, int taskId) { - getNextAppTransitionStartRect(taskId, mTmpRect); + @Nullable Rect surfaceInsets, WindowContainer container) { + getNextAppTransitionStartRect(container, mTmpRect); return createAspectScaledThumbnailFreeformAnimationLocked(mTmpRect, frame, surfaceInsets, true); } private Animation createAspectScaledThumbnailExitFreeformAnimationLocked(Rect frame, - @Nullable Rect surfaceInsets, int taskId) { - getNextAppTransitionStartRect(taskId, mTmpRect); + @Nullable Rect surfaceInsets, WindowContainer container) { + getNextAppTransitionStartRect(container, mTmpRect); return createAspectScaledThumbnailFreeformAnimationLocked(frame, mTmpRect, surfaceInsets, false); } @@ -1469,10 +1471,10 @@ public class AppTransition implements Dump { * leaving, and the activity that is entering. */ Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, Rect containingFrame, - int transit, int taskId) { + int transit, WindowContainer container) { final int appWidth = containingFrame.width(); final int appHeight = containingFrame.height(); - final GraphicBuffer thumbnailHeader = getAppTransitionThumbnailHeader(taskId); + final GraphicBuffer thumbnailHeader = getAppTransitionThumbnailHeader(container); Animation a; getDefaultNextAppTransitionStartRect(mTmpRect); final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth; @@ -1615,7 +1617,7 @@ public class AppTransition implements Dump { Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode, int orientation, Rect frame, Rect displayFrame, Rect insets, @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction, - boolean freeform, int taskId) { + boolean freeform, WindowContainer container) { Animation a; if (isKeyguardGoingAwayTransit(transit) && enter) { a = loadKeyguardExitAnimation(transit); @@ -1679,7 +1681,7 @@ public class AppTransition implements Dump { mNextAppTransitionScaleUp = (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP); a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter), - frame, transit, taskId); + frame, transit, container); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b " + "Callers=%s", @@ -1692,7 +1694,7 @@ public class AppTransition implements Dump { (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP); a = createAspectScaledThumbnailEnterExitAnimationLocked( getThumbnailTransitionState(enter), uiMode, orientation, transit, frame, - insets, surfaceInsets, stableInsets, freeform, taskId); + insets, surfaceInsets, stableInsets, freeform, container); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b " + "Callers=%s", @@ -1895,7 +1897,11 @@ public class AppTransition implements Dump { for (int i = 0; i < specs.length; i++) { AppTransitionAnimationSpec spec = specs[i]; if (spec != null) { - mNextAppTransitionAnimationsSpecs.put(spec.taskId, spec); + final WindowContainer container = findTask(spec.taskId); + if (container == null) { + continue; + } + mNextAppTransitionAnimationsSpecs.put(container.hashCode(), spec); if (i == 0) { // In full screen mode, the transition code depends on the default spec // to be set. @@ -1912,6 +1918,19 @@ public class AppTransition implements Dump { } } + private Task findTask(int taskId) { + if (taskId < 0) { + return null; + } + ArrayList<Task> tasks = new ArrayList<>(); + mDisplayContent.forAllTasks(task -> { + if (task.mTaskId == taskId) { + tasks.add(task); + } + }); + return tasks.size() == 1 ? tasks.get(0) : null; + } + void overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp) { diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 3bda0c25a6b0..bef6af350269 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -410,7 +410,7 @@ public class AppTransitionController { ActivityRecord activity = apps.valueAt(i); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", activity); activity.cancelAnimationOnly(); - activity.applyAnimationLocked(null, transit, true, false); + activity.applyAnimation(null, transit, true, false); activity.updateReportedVisibilityLocked(); mService.openSurfaceTransaction(); try { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2d1d29710c95..89568ebf4277 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -106,6 +106,8 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON; import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; @@ -2363,7 +2365,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo @Override void removeIfPossible() { - if (isAnimating()) { + if (isAnimating(TRANSITION | PARENTS)) { mDeferredRemoval = true; return; } @@ -3165,13 +3167,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // to look at all windows below the current target that are in this app, finding the // highest visible one in layering. WindowState highestTarget = null; - if (activity.isSelfAnimating()) { + if (activity.isAnimating(TRANSITION)) { highestTarget = activity.getHighestAnimLayerWindow(curTarget); } if (highestTarget != null) { - if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget - + " animating=" + highestTarget.isAnimating()); + if (DEBUG_INPUT_METHOD) { + Slog.v(TAG_WM, mAppTransition + " " + highestTarget + " animating=" + + highestTarget.isAnimating(TRANSITION | PARENTS)); + } if (mAppTransition.isTransitionSet()) { // If we are currently setting up for an animation, hold everything until we @@ -4322,7 +4326,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // The split screen divider anchor is located above the split screen window. layerForSplitScreenDividerAnchor = layer++; } - if (s.isTaskAnimating() || s.isAppAnimating()) { + if (s.isTaskAnimating() || s.isAppTransitioning()) { // The animation layer is located above the highest animating stack and no // higher. layerForAnimationLayer = layer++; @@ -4651,7 +4655,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // so it get's layered above the starting window. if (imeTarget != null && !(imeTarget.mActivityRecord != null && imeTarget.mActivityRecord.hasStartingWindow()) - && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating()) + && (!(imeTarget.inSplitScreenWindowingMode() + || imeTarget.mToken.isAppTransitioning()) && (imeTarget.getSurfaceControl() != null))) { mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(), // TODO: We need to use an extra level on the app surface to ensure diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index 7f9e76b0c7e0..1ebbb0294204 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -4,6 +4,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import static com.android.server.wm.ActivityRecord.INVALID_PID; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -14,6 +15,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; import android.view.IWindow; +import android.view.InputApplicationHandle; import android.view.KeyEvent; import android.view.WindowManager; @@ -80,7 +82,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal * Called by the InputManager. */ @Override - public long notifyANR(IBinder token, String reason) { + public long notifyANR(InputApplicationHandle inputApplicationHandle, + IBinder token, String reason) { ActivityRecord activity = null; WindowState windowState = null; boolean aboveSystem = false; @@ -93,6 +96,10 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal } } + if (activity == null && inputApplicationHandle != null) { + activity = ActivityRecord.forTokenLocked(inputApplicationHandle.token); + } + if (windowState != null) { Slog.i(TAG_WM, "Input event dispatching timed out " + "sending to " + windowState.mAttrs.getTitle() @@ -122,7 +129,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. final boolean abort = activity.keyDispatchingTimedOut(reason, - windowState.mSession.mPid); + (windowState != null) ? windowState.mSession.mPid : INVALID_PID); if (!abort) { // The activity manager declined to abort dispatching. // Wait a bit longer and timeout again later. diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java index 0c0cf9262e44..e0a7b18f40c0 100644 --- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java +++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java @@ -16,6 +16,9 @@ package com.android.server.wm; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; + import android.util.ArraySet; import android.view.Display.Mode; import android.view.DisplayInfo; @@ -67,7 +70,7 @@ class RefreshRatePolicy { // If app is animating, it's not able to control refresh rate because we want the animation // to run in default refresh rate. - if (w.isAnimating()) { + if (w.isAnimating(TRANSITION | PARENTS)) { return 0; } diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index c23ffd964e06..efd124164779 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -41,7 +41,6 @@ import com.android.internal.util.FastPrintWriter; import com.android.server.protolog.ProtoLogImpl; import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; -import com.android.server.wm.utils.InsetUtils; import java.io.PrintWriter; import java.io.StringWriter; @@ -76,20 +75,20 @@ class RemoteAnimationController implements DeathRecipient { } /** - * Creates an animation record for each individual {@link ActivityRecord}. + * Creates an animation record for each individual {@link WindowContainer}. * - * @param activity The app to animate. + * @param windowContainer The windows to animate. * @param position The position app bounds, in screen coordinates. * @param stackBounds The stack bounds of the app relative to position. * @param startBounds The stack bounds before the transition, in screen coordinates * @return The record representing animation(s) to run on the app. */ - RemoteAnimationRecord createRemoteAnimationRecord(ActivityRecord activity, Point position, - Rect stackBounds, Rect startBounds) { - ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): token=%s", - activity); + RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer, + Point position, Rect stackBounds, Rect startBounds) { + ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s", + windowContainer); final RemoteAnimationRecord adapters = - new RemoteAnimationRecord(activity, position, stackBounds, startBounds); + new RemoteAnimationRecord(windowContainer, position, stackBounds, startBounds); mPendingAnimations.add(adapters); return adapters; } @@ -169,11 +168,12 @@ class RemoteAnimationController implements DeathRecipient { final RemoteAnimationRecord wrappers = mPendingAnimations.get(i); final RemoteAnimationTarget target = wrappers.createRemoteAnimationTarget(); if (target != null) { - ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd token=%s", wrappers.mActivityRecord); + ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd container=%s", + wrappers.mWindowContainer); targets.add(target); } else { - ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tRemove token=%s", - wrappers.mActivityRecord); + ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tRemove container=%s", + wrappers.mWindowContainer); // We can't really start an animation but we still need to make sure to finish the // pending animation that was started by SurfaceAnimator @@ -228,7 +228,8 @@ class RemoteAnimationController implements DeathRecipient { .onAnimationFinished(adapters.mThumbnailAdapter); } mPendingAnimations.remove(i); - ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tapp=%s", adapters.mActivityRecord); + ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tcontainer=%s", + adapters.mWindowContainer); } for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) { @@ -332,7 +333,7 @@ class RemoteAnimationController implements DeathRecipient { }; /** - * Contains information about a remote-animation for one AppWindowToken. This keeps track of, + * Contains information about a remote-animation for one WindowContainer. This keeps track of, * potentially, multiple animating surfaces (AdapterWrappers) associated with one * Window/Transition. For example, a change transition has an adapter controller for the * main window and an adapter controlling the start-state snapshot. @@ -345,12 +346,12 @@ class RemoteAnimationController implements DeathRecipient { RemoteAnimationAdapterWrapper mAdapter; RemoteAnimationAdapterWrapper mThumbnailAdapter = null; RemoteAnimationTarget mTarget; - final ActivityRecord mActivityRecord; + final WindowContainer mWindowContainer; final Rect mStartBounds; - RemoteAnimationRecord(ActivityRecord activityRecord, Point endPos, Rect endBounds, + RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect endBounds, Rect startBounds) { - mActivityRecord = activityRecord; + mWindowContainer = windowContainer; mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, endBounds); if (startBounds != null) { mStartBounds = new Rect(startBounds); @@ -366,31 +367,20 @@ class RemoteAnimationController implements DeathRecipient { } RemoteAnimationTarget createRemoteAnimationTarget() { - final Task task = mActivityRecord.getTask(); - final WindowState mainWindow = mActivityRecord.findMainWindow(); - if (task == null || mainWindow == null || mAdapter == null + if (mAdapter == null || mAdapter.mCapturedFinishCallback == null || mAdapter.mCapturedLeash == null) { return null; } - final Rect insets = new Rect(); - mainWindow.getContentInsets(insets); - InsetUtils.addInsets(insets, mActivityRecord.getLetterboxInsets()); - mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(), - mAdapter.mCapturedLeash, !mActivityRecord.fillsParent(), - mainWindow.mWinAnimator.mLastClipRect, insets, - mActivityRecord.getPrefixOrderIndex(), mAdapter.mPosition, - mAdapter.mStackBounds, task.getWindowConfiguration(), false /*isNotInRecents*/, - mThumbnailAdapter != null ? mThumbnailAdapter.mCapturedLeash : null, - mStartBounds); + mTarget = mWindowContainer.createRemoteAnimationTarget(this); return mTarget; } - private int getMode() { - final DisplayContent dc = mActivityRecord.getDisplayContent(); - if (dc.mOpeningApps.contains(mActivityRecord)) { + int getMode() { + final DisplayContent dc = mWindowContainer.getDisplayContent(); + if (dc.mOpeningApps.contains(mWindowContainer)) { return RemoteAnimationTarget.MODE_OPENING; - } else if (dc.mChangingApps.contains(mActivityRecord)) { + } else if (dc.mChangingApps.contains(mWindowContainer)) { return RemoteAnimationTarget.MODE_CHANGING; } else { return RemoteAnimationTarget.MODE_CLOSING; @@ -398,12 +388,12 @@ class RemoteAnimationController implements DeathRecipient { } } - private class RemoteAnimationAdapterWrapper implements AnimationAdapter { + class RemoteAnimationAdapterWrapper implements AnimationAdapter { private final RemoteAnimationRecord mRecord; SurfaceControl mCapturedLeash; private OnAnimationFinishedCallback mCapturedFinishCallback; - private final Point mPosition = new Point(); - private final Rect mStackBounds = new Rect(); + final Point mPosition = new Point(); + final Rect mStackBounds = new Rect(); RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position, Rect stackBounds) { @@ -423,7 +413,7 @@ class RemoteAnimationController implements DeathRecipient { ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation"); // Restore z-layering, position and stack crop until client has a chance to modify it. - t.setLayer(animationLeash, mRecord.mActivityRecord.getPrefixOrderIndex()); + t.setLayer(animationLeash, mRecord.mWindowContainer.getPrefixOrderIndex()); if (mRecord.mStartBounds != null) { t.setPosition(animationLeash, mRecord.mStartBounds.left, mRecord.mStartBounds.top); t.setWindowCrop(animationLeash, mRecord.mStartBounds.width(), @@ -464,7 +454,7 @@ class RemoteAnimationController implements DeathRecipient { @Override public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("token="); pw.println(mRecord.mActivityRecord); + pw.print(prefix); pw.print("container="); pw.println(mRecord.mWindowContainer); if (mRecord.mTarget != null) { pw.print(prefix); pw.println("Target:"); mRecord.mTarget.dump(pw, prefix + " "); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 17f5abdda2c7..f5d3affa89ef 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -787,7 +787,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } - if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppAnimating()) { + if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppTransitioning()) { // We have finished the animation of an app transition. To do this, we have // delayed a lot of operations like showing and hiding apps, moving apps in // Z-order, etc. diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index bf7dd57e82ed..92ff2dc96ab3 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -28,13 +28,14 @@ import static com.android.server.EventLogTags.WM_TASK_REMOVED; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS; import static com.android.server.wm.TaskProto.BOUNDS; -import static com.android.server.wm.TaskProto.DEFER_REMOVAL; import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS; import static com.android.server.wm.TaskProto.FILLS_PARENT; import static com.android.server.wm.TaskProto.ID; import static com.android.server.wm.TaskProto.SURFACE_HEIGHT; import static com.android.server.wm.TaskProto.SURFACE_WIDTH; import static com.android.server.wm.TaskProto.WINDOW_CONTAINER; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -50,6 +51,7 @@ import android.util.EventLog; import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.Display; +import android.view.RemoteAnimationTarget; import android.view.Surface; import android.view.SurfaceControl; @@ -204,7 +206,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta // No reason to defer removal of a Task that doesn't have any child. return false; } - return hasWindowsAlive() && mStack.isSelfOrChildAnimating(); + return hasWindowsAlive() && mStack.isAnimating(TRANSITION | CHILDREN); } @Override @@ -645,6 +647,18 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta return getAppAnimationLayer(ANIMATION_LAYER_HOME); } + boolean shouldAnimate() { + // Don't animate while the task runs recents animation but only if we are in the mode + // where we cancel with deferred screenshot, which means that the controller has + // transformed the task. + final RecentsAnimationController controller = mWmService.getRecentsAnimationController(); + if (controller != null && controller.isAnimatingTask(this) + && controller.shouldDeferCancelUntilNextTransition()) { + return false; + } + return true; + } + @Override SurfaceControl.Builder makeSurface() { return super.makeSurface().setMetadata(METADATA_TASK_ID, mTaskId); @@ -660,6 +674,22 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta return false; } + /** + * @return {@code true} if changing app transition is running. + */ + @Override + boolean isChangingAppTransition() { + final ActivityRecord activity = getTopVisibleActivity(); + return activity != null && getDisplayContent().mChangingApps.contains(activity); + } + + @Override + RemoteAnimationTarget createRemoteAnimationTarget( + RemoteAnimationController.RemoteAnimationRecord record) { + final ActivityRecord activity = getTopVisibleActivity(); + return activity != null ? activity.createRemoteAnimationTarget(record) : null; + } + WindowState getTopVisibleAppMainWindow() { final ActivityRecord activity = getTopVisibleActivity(); return activity != null ? activity.findMainWindow() : null; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 355224536066..8f8c7e7caac6 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -52,6 +52,8 @@ import static com.android.server.wm.StackProto.ID; import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT; import static com.android.server.wm.StackProto.TASKS; import static com.android.server.wm.StackProto.WINDOW_CONTAINER; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -69,6 +71,7 @@ import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.DisplayCutout; import android.view.DisplayInfo; +import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import com.android.internal.annotations.VisibleForTesting; @@ -934,7 +937,7 @@ public class TaskStack extends WindowContainer<Task> implements @Override void removeIfPossible() { - if (isSelfOrChildAnimating()) { + if (isAnimating(TRANSITION | CHILDREN)) { mDeferRemoval = true; return; } @@ -1792,7 +1795,7 @@ public class TaskStack extends WindowContainer<Task> implements /** Returns true if a removal action is still being deferred. */ boolean checkCompleteDeferredRemoval() { - if (isSelfOrChildAnimating()) { + if (isAnimating(TRANSITION | CHILDREN)) { return true; } if (mDeferRemoval) { @@ -1866,4 +1869,11 @@ public class TaskStack extends WindowContainer<Task> implements AnimatingActivityRegistry getAnimatingActivityRegistry() { return mAnimatingActivityRegistry; } + + @Override + RemoteAnimationTarget createRemoteAnimationTarget( + RemoteAnimationController.RemoteAnimationRecord record) { + final Task task = getTopChild(); + return task != null ? task.createRemoteAnimationTarget(record) : null; + } } diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 1e13aef2f8eb..3632284fdeb6 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -24,6 +24,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; @@ -118,7 +120,8 @@ class WallpaperController { } mFindResults.resetTopWallpaper = true; - if (w.mActivityRecord != null && w.mActivityRecord.isHidden() && !w.mActivityRecord.isSelfAnimating()) { + if (w.mActivityRecord != null && w.mActivityRecord.isHidden() + && !w.mActivityRecord.isAnimating(TRANSITION)) { // If this window's app token is hidden and not animating, it is of no interest to us. if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w); @@ -136,7 +139,7 @@ class WallpaperController { } final boolean keyguardGoingAwayWithWallpaper = (w.mActivityRecord != null - && w.mActivityRecord.isSelfAnimating() + && w.mActivityRecord.isAnimating(TRANSITION) && AppTransition.isKeyguardGoingAwayTransit(w.mActivityRecord.getTransit()) && (w.mActivityRecord.getTransitFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0); @@ -159,7 +162,8 @@ class WallpaperController { final RecentsAnimationController recentsAnimationController = mService.getRecentsAnimationController(); - final boolean animationWallpaper = w.mActivityRecord != null && w.mActivityRecord.getAnimation() != null + final boolean animationWallpaper = w.mActivityRecord != null + && w.mActivityRecord.getAnimation() != null && w.mActivityRecord.getAnimation().getShowWallpaper(); final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0 || animationWallpaper; @@ -173,7 +177,7 @@ class WallpaperController { && (mWallpaperTarget == w || w.isDrawFinishedLw())) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w); mFindResults.setWallpaperTarget(w); - if (w == mWallpaperTarget && w.isAnimating()) { + if (w == mWallpaperTarget && w.isAnimating(TRANSITION | PARENTS)) { // The current wallpaper target is animating, so we'll look behind it for // another possible target and figure out what is going on later. if (DEBUG_WALLPAPER) Slog.v(TAG, @@ -224,19 +228,19 @@ class WallpaperController { if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") + " animating=" + ((wallpaperTarget != null && wallpaperTarget.mActivityRecord != null) - ? wallpaperTarget.mActivityRecord.isSelfAnimating() : null) + ? wallpaperTarget.mActivityRecord.isAnimating(TRANSITION) : null) + " prev=" + mPrevWallpaperTarget + " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent); return (wallpaperTarget != null && (!wallpaperTarget.mObscured || isAnimatingWithRecentsComponent || (wallpaperTarget.mActivityRecord != null - && wallpaperTarget.mActivityRecord.isSelfAnimating()))) + && wallpaperTarget.mActivityRecord.isAnimating(TRANSITION)))) || mPrevWallpaperTarget != null; } boolean isWallpaperTargetAnimating() { - return mWallpaperTarget != null && mWallpaperTarget.isAnimating() + return mWallpaperTarget != null && mWallpaperTarget.isAnimating(TRANSITION | PARENTS) && (mWallpaperTarget.mActivityRecord == null || !mWallpaperTarget.mActivityRecord.isWaitingForTransitionStart()); } diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 3a1d6e047fa8..f7525a913e33 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -17,6 +17,8 @@ package com.android.server.wm; import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -192,7 +194,7 @@ public class WindowAnimator { mService.mWindowPlacerLocked.requestTraversal(); } - final boolean rootAnimating = mService.mRoot.isSelfOrChildAnimating(); + final boolean rootAnimating = mService.mRoot.isAnimating(TRANSITION | CHILDREN); if (rootAnimating && !mLastRootAnimating) { // Usually app transitions but quite a load onto the system already (with all the diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index a620a7cfe42b..7ce2b5eb727b 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -24,8 +24,15 @@ import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; +import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.SurfaceControl.Transaction; +import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; +import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER; import static com.android.server.wm.WindowContainerProto.ORIENTATION; import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR; @@ -33,7 +40,9 @@ import static com.android.server.wm.WindowContainerProto.VISIBLE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 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.logWithStack; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; +import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import android.annotation.CallSuper; import android.annotation.IntDef; @@ -45,17 +54,24 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.Debug; import android.os.IBinder; +import android.os.Trace; +import android.util.Pair; import android.util.Pools; import android.util.Slog; import android.util.proto.ProtoOutputStream; +import android.view.DisplayInfo; import android.view.MagnificationSpec; +import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Builder; import android.view.SurfaceSession; +import android.view.WindowManager; +import android.view.animation.Animation; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ToBooleanFunction; import com.android.server.policy.WindowManagerPolicy; +import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.Animatable; import java.io.PrintWriter; @@ -155,6 +171,29 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< private final Configuration mTmpConfig = new Configuration(); + /** Interface for {@link #isAnimating} to check which cases for the container is animating. */ + public interface AnimationFlags { + /** + * A bit flag indicates that {@link #isAnimating} should also return {@code true} + * even though the container is not yet animating, but the window container or its + * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition} + * that is pending so an animation starts soon. + */ + int TRANSITION = 1; + + /** + * A bit flag indicates that {@link #isAnimating} should also check if one of the + * ancestors of the container are animating in addition to the container itself. + */ + int PARENTS = 2; + + /** + * A bit flag indicates that {@link #isAnimating} should also check if one of the + * descendants of the container are animating in addition to the container itself. + */ + int CHILDREN = 4; + } + /** * Callback which is triggered while changing the parent, after setting up the surface but * before asking the parent to assign child layers. @@ -163,6 +202,47 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< void onPreAssignChildLayers(); } + /** + * True if this an AppWindowToken and the activity which created this was launched with + * ActivityOptions.setLaunchTaskBehind. + * + * TODO(b/142617871): We run a special animation when the activity was launched with that + * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly + * selected to suppress an animation, and remove this flag. + */ + boolean mLaunchTaskBehind; + + /** + * If we are running an animation, this determines the transition type. Must be one of + * {@link AppTransition#TransitionFlags}. + */ + int mTransit; + + /** + * If we are running an animation, this determines the flags during this animation. Must be a + * bitwise combination of AppTransition.TRANSIT_FLAG_* constants. + */ + int mTransitFlags; + + /** Whether this container should be boosted at the top of all its siblings. */ + @VisibleForTesting boolean mNeedsZBoost; + + /** Layer used to constrain the animation to a container's stack bounds. */ + SurfaceControl mAnimationBoundsLayer; + + /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */ + boolean mNeedsAnimationBoundsLayer; + + /** + * This gets used during some open/close transitions as well as during a change transition + * where it represents the starting-state snapshot. + */ + AppWindowThumbnail mThumbnail; + final Rect mTransitStartRect = new Rect(); + final Point mTmpPoint = new Point(); + protected final Rect mTmpRect = new Rect(); + final Rect mTmpPrevBounds = new Rect(); + WindowContainer(WindowManagerService wms) { mWmService = wms; mPendingTransaction = wms.mTransactionFactory.get(); @@ -642,51 +722,78 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } /** - * @return Whether our own container is running an animation or any child, no matter how deep in - * the hierarchy, is animating. + * @return {@code true} when this container or its related containers are running an + * animation, {@code false} otherwise. + * + * By default this predicate only checks if this container itself is actually running an + * animation, but you can extend the check target over its relatives, or relax the condition + * so that this can return {@code true} if an animation starts soon by giving a combination + * of {@link #AnimationFlags}. + * + * Note that you can give a combination of bitmask flags to specify targets and condition for + * checking animating status. + * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this + * container itself or one of its parents is running an animation or waiting for an app + * transition. + * + * Note that TRANSITION propagates to parents and children as well. + * + * {@see AnimationFlags#TRANSITION} + * {@see AnimationFlags#PARENTS} + * {@see AnimationFlags#CHILDREN} */ - boolean isSelfOrChildAnimating() { - if (isSelfAnimating()) { + final boolean isAnimating(int flags) { + if (mSurfaceAnimator.isAnimating()) { return true; } - for (int j = mChildren.size() - 1; j >= 0; j--) { - final WindowContainer wc = mChildren.get(j); - if (wc.isSelfOrChildAnimating()) { + if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) { + return true; + } + if ((flags & PARENTS) != 0) { + final WindowContainer parent = getParent(); + if (parent != null && parent.isAnimating(flags & ~CHILDREN)) { return true; } } + if ((flags & CHILDREN) != 0) { + for (int i = 0; i < mChildren.size(); ++i) { + final WindowContainer wc = mChildren.get(i); + if (wc.isAnimating(flags & ~PARENTS)) { + return true; + } + } + } return false; } /** - * @return Whether our own container is running an animation or our parent is animating. This - * doesn't consider whether children are animating. + * @return {@code true} when the container is waiting the app transition start, {@code false} + * otherwise. */ - boolean isAnimating() { - - // We are animating if we ourselves are animating or if our parent is animating. - return isSelfAnimating() || mParent != null && mParent.isAnimating(); + boolean isWaitingForTransitionStart() { + return false; } /** - * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken} - * that is {@link #isSelfAnimating}; {@code false} otherwise. + * @return {@code true} if in this subtree of the hierarchy we have an + * {@ode ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise. */ - boolean isAppAnimating() { - for (int j = mChildren.size() - 1; j >= 0; j--) { - final WindowContainer wc = mChildren.get(j); - if (wc.isAppAnimating()) { - return true; - } - } - return false; + boolean isAppTransitioning() { + return forAllActivities(app -> app.isAnimating(TRANSITION)); } /** * @return Whether our own container running an animation at the moment. */ - boolean isSelfAnimating() { - return mSurfaceAnimator.isAnimating(); + final boolean isAnimating() { + return isAnimating(0 /* self only */); + } + + /** + * @return {@code true} if the container is in changing app transition. + */ + boolean isChangingAppTransition() { + return false; } void sendAppVisibilityToClients() { @@ -988,10 +1095,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< wrapper.release(); } - void forAllActivities(Consumer<ActivityRecord> callback) { + boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) { for (int i = mChildren.size() - 1; i >= 0; --i) { - mChildren.get(i).forAllActivities(callback); + if (mChildren.get(i).forAllActivities(callback)) { + return true; + } } + return false; } void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) { @@ -1374,6 +1484,203 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return null; } + // TODO: Remove this and use #getBounds() instead once we set an app transition animation + // on TaskStack. + Rect getAnimationBounds(int appStackClipMode) { + return getBounds(); + } + + /** + * Applies the app transition animation according the given the layout properties in the + * window hierarchy. + * + * @param lp The layout parameters of the window. + * @param transit The app transition type indicates what kind of transition to be applied. + * @param enter Whether the app transition is entering transition or not. + * @param isVoiceInteraction Whether the container is participating in voice interaction or not. + * + * @return {@code true} when the container applied the app transition, {@code false} if the + * app transition is disabled or skipped. + * + * @see #getAnimationAdapter + */ + boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, + boolean isVoiceInteraction) { + if (mWmService.mDisableTransitionAnimation) { + ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, + "applyAnimation: transition animation is disabled or skipped. " + + "container=%s", this); + cancelAnimation(); + return false; + } + + // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason + // to animate and it can cause strange artifacts when we unfreeze the display if some + // different animation is running. + try { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation"); + if (okToAnimate()) { + Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp, transit, + enter, isVoiceInteraction); + AnimationAdapter adapter = adapters.first; + AnimationAdapter thumbnailAdapter = adapters.second; + if (adapter != null) { + startAnimation(getPendingTransaction(), adapter, !isVisible()); + if (adapter.getShowWallpaper()) { + mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; + } + if (thumbnailAdapter != null) { + mThumbnail.startAnimation( + getPendingTransaction(), thumbnailAdapter, !isVisible()); + } + } + } else { + cancelAnimation(); + } + } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + } + + return isAnimating(); + } + + /** + * Gets the {@link AnimationAdapter} according the given window layout properties in the window + * hierarchy. + * + * @return The return value will always contain two elements, one for normal animations and the + * other for thumbnail animation, both can be {@code null}. + * + * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord + * @See LocalAnimationAdapter + */ + Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp, + int transit, boolean enter, boolean isVoiceInteraction) { + final Pair<AnimationAdapter, AnimationAdapter> resultAdapters; + final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode(); + + // Separate position and size for use in animators. + mTmpRect.set(getAnimationBounds(appStackClipMode)); + mTmpPoint.set(mTmpRect.left, mTmpRect.top); + mTmpRect.offsetTo(0, 0); + + final RemoteAnimationController controller = + getDisplayContent().mAppTransition.getRemoteAnimationController(); + final boolean isChanging = AppTransition.isChangeTransit(transit) && enter + && isChangingAppTransition(); + + // Delaying animation start isn't compatible with remote animations at all. + if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) { + final RemoteAnimationController.RemoteAnimationRecord adapters = + controller.createRemoteAnimationRecord(this, mTmpPoint, mTmpRect, + (isChanging ? mTransitStartRect : null)); + resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter); + } else if (isChanging) { + final float durationScale = mWmService.getTransitionAnimationScaleLocked(); + final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo(); + mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y); + + AnimationAdapter adapter = new LocalAnimationAdapter( + new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo, + durationScale, true /* isAppAnimation */, false /* isThumbnail */), + getSurfaceAnimationRunner()); + + AnimationAdapter thumbnailAdapter = null; + if (mThumbnail != null) { + thumbnailAdapter = new LocalAnimationAdapter( + new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo, + durationScale, true /* isAppAnimation */, true /* isThumbnail */), + getSurfaceAnimationRunner()); + } + resultAdapters = new Pair<>(adapter, thumbnailAdapter); + mTransit = transit; + mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags(); + } else { + mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM); + final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction); + + if (a != null) { + // Only apply corner radius to animation if we're not in multi window mode. + // We don't want rounded corners when in pip or split screen. + final float windowCornerRadius = !inMultiWindowMode() + ? getDisplayContent().getWindowCornerRadius() + : 0; + AnimationAdapter adapter = new LocalAnimationAdapter( + new WindowAnimationSpec(a, mTmpPoint, mTmpRect, + getDisplayContent().mAppTransition.canSkipFirstFrame(), + appStackClipMode, true /* isAppAnimation */, windowCornerRadius), + getSurfaceAnimationRunner()); + + resultAdapters = new Pair<>(adapter, null); + mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP; + mTransit = transit; + mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags(); + } else { + resultAdapters = new Pair<>(null, null); + } + } + return resultAdapters; + } + + final SurfaceAnimationRunner getSurfaceAnimationRunner() { + return mWmService.mSurfaceAnimationRunner; + } + + private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, + boolean isVoiceInteraction) { + final DisplayContent displayContent = getDisplayContent(); + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final int width = displayInfo.appWidth; + final int height = displayInfo.appHeight; + ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this); + + // Determine the visible rect to calculate the thumbnail clip with + // getAnimationFrames. + final Rect frame = new Rect(0, 0, width, height); + final Rect displayFrame = new Rect(0, 0, + displayInfo.logicalWidth, displayInfo.logicalHeight); + final Rect insets = new Rect(); + final Rect stableInsets = new Rect(); + final Rect surfaceInsets = new Rect(); + getAnimationFrames(frame, insets, stableInsets, surfaceInsets); + + if (mLaunchTaskBehind) { + // Differentiate the two animations. This one which is briefly on the screen + // gets the !enter animation, and the other one which remains on the + // screen gets the enter animation. Both appear in the mOpeningApps set. + enter = false; + } + ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, + "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s " + + "surfaceInsets=%s", + AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets); + final Configuration displayConfig = displayContent.getConfiguration(); + final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter, + displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets, + surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this); + if (a != null) { + if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this); + final int containingWidth = frame.width(); + final int containingHeight = frame.height(); + a.initialize(containingWidth, containingHeight, width, height); + a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked()); + } + return a; + } + + RemoteAnimationTarget createRemoteAnimationTarget( + RemoteAnimationController.RemoteAnimationRecord record) { + return null; + } + + boolean okToDisplay() { + return mDisplayContent != null && mDisplayContent.okToDisplay(); + } + + boolean okToAnimate() { + return mDisplayContent != null && mDisplayContent.okToAnimate(); + } + @Override public void commitPendingTransaction() { scheduleAnimation(); @@ -1473,6 +1780,26 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return getBounds(); } + /** + * The {@code outFrame} retrieved by this method specifies where the animation will finish + * the entrance animation, as the next frame will display the window at these coordinates. In + * case of exit animation, this is where the animation will start, as the frame before the + * animation is displaying the window at these bounds. + * + * @param outFrame The bounds where entrance animation finishes or exit animation starts. + * @param outInsets Insets that are covered by system windows. + * @param outStableInsets Insets that determine the area covered by the stable system windows. + * @param outSurfaceInsets Positive insets between the drawing surface and window content. + */ + void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, + Rect outSurfaceInsets) { + final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo(); + outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight); + outInsets.setEmpty(); + outStableInsets.setEmpty(); + outSurfaceInsets.setEmpty(); + } + void getRelativeDisplayedPosition(Point outPos) { final Rect dispBounds = getDisplayedBounds(); outPos.set(dispBounds.left, dispBounds.top); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 085b0f66702a..ab937e0a4e23 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -94,6 +94,9 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; import static com.android.server.wm.ProtoLogGroup.WM_ERROR; import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; @@ -2418,7 +2421,7 @@ public class WindowManagerService extends IWindowManager.Stub if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { focusMayChange = true; win.mAnimatingExit = true; - } else if (win.isAnimating()) { + } else if (win.isAnimating(TRANSITION | PARENTS)) { // Currently in a hide animation... turn this into // an exit. win.mAnimatingExit = true; @@ -7618,7 +7621,7 @@ public class WindowManagerService extends IWindowManager.Stub private void waitForAnimationsToComplete() { synchronized (mGlobalLock) { long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS; - while (mRoot.isSelfOrChildAnimating() && timeoutRemaining > 0) { + while (mRoot.isAnimating(TRANSITION | CHILDREN) && timeoutRemaining > 0) { long startTime = System.currentTimeMillis(); try { mGlobalLock.wait(timeoutRemaining); @@ -7627,7 +7630,7 @@ public class WindowManagerService extends IWindowManager.Stub timeoutRemaining -= (System.currentTimeMillis() - startTime); } - if (mRoot.isSelfOrChildAnimating()) { + if (mRoot.isAnimating(TRANSITION | CHILDREN)) { Log.w(TAG, "Timed out waiting for animations to complete."); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index f0ea13d2c68a..f7402e1dfea4 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -98,6 +98,8 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RESIZE; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; @@ -1492,7 +1494,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean hasContentToDisplay() { if (!mAppFreezing && isDrawnLw() && (mViewVisibility == View.VISIBLE - || (isAnimating() && !getDisplayContent().mAppTransition.isTransitionSet()))) { + || (isAnimating(TRANSITION | PARENTS) + && !getDisplayContent().mAppTransition.isTransitionSet()))) { return true; } @@ -1550,8 +1553,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this? boolean isWinVisibleLw() { - return (mActivityRecord == null || !mActivityRecord.hiddenRequested || mActivityRecord.isSelfAnimating()) - && isVisible(); + return (mActivityRecord == null || !mActivityRecord.hiddenRequested + || mActivityRecord.isAnimating(TRANSITION)) && isVisible(); } /** @@ -1597,9 +1600,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final ActivityRecord atoken = mActivityRecord; if (atoken != null) { return ((!isParentWindowHidden() && !atoken.hiddenRequested) - || isAnimating()); + || isAnimating(TRANSITION | PARENTS)); } - return !isParentWindowHidden() || isAnimating(); + return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS); } /** @@ -1634,7 +1637,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean parentAndClientVisible = !isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.isHidden(); return mHasSurface && isVisibleByPolicy() && !mDestroying - && (parentAndClientVisible || isAnimating()); + && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS)); } // TODO: Another visibility method that was added late in the release to minimize risk. @@ -1664,7 +1667,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final ActivityRecord atoken = mActivityRecord; return isDrawnLw() && isVisibleByPolicy() && ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested)) - || isAnimating()); + || isAnimating(TRANSITION | PARENTS)); } /** @@ -1672,7 +1675,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ @Override public boolean isAnimatingLw() { - return isAnimating(); + return isAnimating(TRANSITION | PARENTS); } @Override @@ -1718,7 +1721,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // to determine if it's occluding apps. return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE) || (mIsWallpaper && mWallpaperVisible)) - && isDrawnLw() && !isAnimating(); + && isDrawnLw() && !isAnimating(TRANSITION | PARENTS); } @Override @@ -1740,7 +1743,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Starting window that's exiting will be removed when the animation finishes. // Mark all relevant flags for that onExitAnimationDone will proceed all the way // to actually remove it. - if (!visible && isVisibleNow() && mActivityRecord.isSelfAnimating()) { + if (!visible && isVisibleNow() && mActivityRecord.isAnimating(TRANSITION)) { mAnimatingExit = true; mRemoveOnExit = true; mWindowRemovalAllowed = true; @@ -2016,8 +2019,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + "mWillReplaceWindow=%b inPendingTransaction=%b mDisplayFrozen=%b " + "callers=%s", this, mWinAnimator.mSurfaceController, mAnimatingExit, mRemoveOnExit, - mHasSurface, mWinAnimator.getShown(), isAnimating(), - mActivityRecord != null && mActivityRecord.isSelfAnimating(), mWillReplaceWindow, + mHasSurface, mWinAnimator.getShown(), + isAnimating(TRANSITION | PARENTS), + mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION), + mWillReplaceWindow, mActivityRecord != null && mActivityRecord.inPendingTransaction, mWmService.mDisplayFrozen, Debug.getCallers(6)); @@ -2076,7 +2081,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit); } } - final boolean isAnimating = isAnimating() + final boolean isAnimating = isAnimating(TRANSITION | PARENTS) && (mActivityRecord == null || !mActivityRecord.isWaitingForTransitionStart()); final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null && mActivityRecord.isLastWindow(this); @@ -2683,10 +2688,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); if (doAnimation) { if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" - + isLegacyPolicyVisibility() + " animating=" + isAnimating()); + + isLegacyPolicyVisibility() + + " animating=" + isAnimating(TRANSITION | PARENTS)); if (!mToken.okToAnimate()) { doAnimation = false; - } else if (isLegacyPolicyVisibility() && !isAnimating()) { + } else if (isLegacyPolicyVisibility() && !isAnimating(TRANSITION | PARENTS)) { // Check for the case where we are currently visible and // not animating; we do not want to do animation at such a // point to become visible when we already are. @@ -2726,7 +2732,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } if (doAnimation) { mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false); - if (!isAnimating()) { + if (!isAnimating(TRANSITION | PARENTS)) { doAnimation = false; } } @@ -4163,9 +4169,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + " tok.hiddenRequested=" + (mActivityRecord != null && mActivityRecord.hiddenRequested) + " tok.hidden=" + (mActivityRecord != null && mActivityRecord.isHidden()) - + " animating=" + isAnimating() + + " animating=" + isAnimating(TRANSITION | PARENTS) + " tok animating=" - + (mActivityRecord != null && mActivityRecord.isSelfAnimating()) + + (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION)) + " Callers=" + Debug.getCallers(4)); } } @@ -4392,7 +4398,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void onExitAnimationDone() { if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit - + " selfAnimating=" + isSelfAnimating()); + + " selfAnimating=" + isAnimating()); if (!mChildren.isEmpty()) { // Copying to a different list as multiple children can be removed. @@ -4415,7 +4421,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - if (isSelfAnimating()) { + if (isAnimating()) { return; } if (mWmService.mAccessibilityController != null) { @@ -4563,25 +4569,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } if (DEBUG_VISIBILITY) { Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawnLw() - + ", animating=" + isAnimating()); + + ", animating=" + isAnimating(TRANSITION | PARENTS)); if (!isDrawnLw()) { Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController + " pv=" + isVisibleByPolicy() + " mDrawState=" + mWinAnimator.mDrawState + " ph=" + isParentWindowHidden() + " th=" + (mActivityRecord != null ? mActivityRecord.hiddenRequested : false) - + " a=" + isAnimating()); + + " a=" + isAnimating(TRANSITION | PARENTS)); } } results.numInteresting++; if (isDrawnLw()) { results.numDrawn++; - if (!isAnimating()) { + if (!isAnimating(TRANSITION | PARENTS)) { results.numVisible++; } results.nowGone = false; - } else if (isAnimating()) { + } else if (isAnimating(TRANSITION | PARENTS)) { results.nowGone = false; } } @@ -4718,7 +4724,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + mRemoveOnExit + ", mDestroying=" + mDestroying); // Cancel the existing exit animation for the next enter animation. - if (isSelfAnimating()) { + if (isAnimating()) { cancelAnimation(); destroySurfaceUnchecked(); } @@ -5398,4 +5404,29 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } return mKeyInterceptionInfo; } + + @Override + void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, + Rect outSurfaceInsets) { + // Containing frame will usually cover the whole screen, including dialog windows. + // For freeform workspace windows it will not cover the whole screen and it also + // won't exactly match the final freeform window frame (e.g. when overlapping with + // the status bar). In that case we need to use the final frame. + if (inFreeformWindowingMode()) { + outFrame.set(getFrameLw()); + } else if (isLetterboxedAppWindow()) { + outFrame.set(getTask().getBounds()); + } else if (isDockedResizing()) { + // If we are animating while docked resizing, then use the stack bounds as the + // animation target (which will be different than the task bounds) + outFrame.set(getTask().getParent().getBounds()); + } else { + outFrame.set(getContainingFrame()); + } + outSurfaceInsets.set(getAttrs().surfaceInsets); + // TODO(b/72757033): These are insets relative to the window frame, but we're really + // interested in the insets relative to the frame we chose in the if-blocks above. + getContentInsets(outInsets); + getStableInsets(outStableInsets); + } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 3f25f89c1a3f..fef3a9d362eb 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -32,6 +32,8 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; @@ -435,7 +437,7 @@ class WindowStateAnimator { return; } - if (!mWin.mActivityRecord.isSelfAnimating()) { + if (!mWin.mActivityRecord.isAnimating(TRANSITION)) { mWin.mActivityRecord.clearAllDrawn(); } else { // Currently animating, persist current state of allDrawn until animation @@ -1169,7 +1171,7 @@ class WindowStateAnimator { w.mToken.hasVisible = true; } } else { - if (DEBUG_ANIM && mWin.isAnimating()) { + if (DEBUG_ANIM && mWin.isAnimating(TRANSITION | PARENTS)) { Slog.v(TAG, "prepareSurface: No changes in animation for " + this); } displayed = true; @@ -1332,7 +1334,7 @@ class WindowStateAnimator { * @return true if an animation has been loaded. */ boolean applyAnimationLocked(int transit, boolean isEntrance) { - if (mWin.isSelfAnimating() && mAnimationIsEntrance == isEntrance) { + if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) { // If we are trying to apply an animation, but already running // an animation of the same type, then just leave that one alone. return true; @@ -1400,7 +1402,7 @@ class WindowStateAnimator { mWin.getDisplayContent().adjustForImeIfNeeded(); } - return mWin.isAnimating(); + return mWin.isAnimating(TRANSITION | PARENTS); } void writeToProto(ProtoOutputStream proto, long fieldId) { diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index ad71237bdf4e..88a1458a783f 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -22,6 +22,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 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.UPDATE_FOCUS_NORMAL; @@ -159,13 +162,10 @@ class WindowToken extends WindowContainer<WindowState> { final int count = mChildren.size(); boolean changed = false; - boolean delayed = false; + final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN); for (int i = 0; i < count; i++) { final WindowState win = mChildren.get(i); - if (win.isAnimating()) { - delayed = true; - } changed |= win.onSetAppExiting(); } @@ -321,14 +321,6 @@ class WindowToken extends WindowContainer<WindowState> { return toString(); } - boolean okToDisplay() { - return mDisplayContent != null && mDisplayContent.okToDisplay(); - } - - boolean okToAnimate() { - return mDisplayContent != null && mDisplayContent.okToAnimate(); - } - /** * Return whether windows from this token can layer above the * system bars, or in other words extend outside of the "Decor Frame" diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index dd2629d31768..35e2436817df 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -709,6 +709,18 @@ void NativeInputManager::notifyConfigurationChanged(nsecs_t when) { checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged"); } +static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env, + const sp<InputApplicationHandle>& inputApplicationHandle) { + if (inputApplicationHandle == nullptr) { + return nullptr; + } + NativeInputApplicationHandle* handle = + static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get()); + + return handle->getInputApplicationHandleObjLocalRef(env); +} + + nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, const sp<IBinder>& token, const std::string& reason) { #if DEBUG_INPUT_DISPATCHER_POLICY @@ -719,12 +731,15 @@ nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApp JNIEnv* env = jniEnv(); ScopedLocalFrame localFrame(env); + jobject inputApplicationHandleObj = + getInputApplicationHandleObjLocalRef(env, inputApplicationHandle); + jobject tokenObj = javaObjectForIBinder(env, token); jstring reasonObj = env->NewStringUTF(reason.c_str()); jlong newTimeout = env->CallLongMethod(mServiceObj, - gServiceClassInfo.notifyANR, tokenObj, - reasonObj); + gServiceClassInfo.notifyANR, inputApplicationHandleObj, tokenObj, + reasonObj); if (checkAndClearExceptionFromCallback(env, "notifyANR")) { newTimeout = 0; // abort dispatch } else { @@ -1865,7 +1880,7 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz, "notifyANR", - "(Landroid/os/IBinder;Ljava/lang/String;)J"); + "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J"); GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz, "filterInputEvent", "(Landroid/view/InputEvent;I)Z"); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 58830487a0fe..2009dbdca448 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -27,6 +27,7 @@ import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_ import android.annotation.NonNull; import android.annotation.StringRes; import android.app.ActivityThread; +import android.app.AppCompatCallbacks; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; @@ -646,6 +647,7 @@ public final class SystemServer { ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat); ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, new PlatformCompatNative(platformCompat)); + AppCompatCallbacks.install(new long[0]); t.traceEnd(); // Wait for installd to finish starting up so that it has a chance to @@ -1133,7 +1135,6 @@ public final class SystemServer { StatusBarManagerService statusBar = null; INotificationManager notification = null; - LocationManagerService location = null; CountryDetectorService countryDetector = null; ILockSettings lockSettings = null; MediaRouterService mediaRouter = null; @@ -1430,12 +1431,7 @@ public final class SystemServer { t.traceEnd(); t.traceBegin("StartLocationManagerService"); - try { - location = new LocationManagerService(context); - ServiceManager.addService(Context.LOCATION_SERVICE, location); - } catch (Throwable e) { - reportWtf("starting Location Manager", e); - } + mSystemServiceManager.startService(LocationManagerService.Lifecycle.class); t.traceEnd(); t.traceBegin("StartCountryDetectorService"); @@ -2019,7 +2015,6 @@ public final class SystemServer { final NetworkStatsService networkStatsF = networkStats; final NetworkPolicyManagerService networkPolicyF = networkPolicy; final ConnectivityService connectivityF = connectivity; - final LocationManagerService locationF = location; final CountryDetectorService countryDetectorF = countryDetector; final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater; final InputManagerService inputManagerF = inputManager; @@ -2175,16 +2170,6 @@ public final class SystemServer { } t.traceEnd(); - - t.traceBegin("MakeLocationServiceReady"); - try { - if (locationF != null) { - locationF.systemRunning(); - } - } catch (Throwable e) { - reportWtf("Notifying Location Service running", e); - } - t.traceEnd(); t.traceBegin("MakeCountryDetectionServiceReady"); try { if (countryDetectorF != null) { diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java index 9e7b80567263..485f436f7f65 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java @@ -38,7 +38,6 @@ import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATU import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION; -import static com.android.server.AlarmManagerService.Constants.KEY_APP_STANDBY_QUOTAS_ENABLED; import static com.android.server.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; import static com.android.server.AlarmManagerService.Constants.KEY_MAX_INTERVAL; import static com.android.server.AlarmManagerService.Constants.KEY_MIN_FUTURITY; @@ -305,6 +304,8 @@ public class AlarmManagerServiceTest { argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING) && filter.hasAction(BatteryManager.ACTION_DISCHARGING))); mChargingReceiver = chargingReceiverCaptor.getValue(); + + setTestableQuotas(); } private void setTestAlarm(int type, long triggerTime, PendingIntent operation) { @@ -342,9 +343,10 @@ public class AlarmManagerServiceTest { } /** + * Lowers quotas to make testing feasible. * Careful while calling as this will replace any existing settings for the calling test. */ - private void setQuotasEnabled(boolean enabled) { + private void setTestableQuotas() { final StringBuilder constantsBuilder = new StringBuilder(); constantsBuilder.append(KEY_MIN_FUTURITY); constantsBuilder.append("=0,"); @@ -353,14 +355,9 @@ public class AlarmManagerServiceTest { constantsBuilder.append("=8,"); constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]); constantsBuilder.append("=5,"); - if (!enabled) { - constantsBuilder.append(KEY_APP_STANDBY_QUOTAS_ENABLED); - constantsBuilder.append("=false,"); - } doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS)); mService.mConstants.onChange(false, null); - assertEquals(mService.mConstants.APP_STANDBY_QUOTAS_ENABLED, enabled); } @Test @@ -481,67 +478,6 @@ public class AlarmManagerServiceTest { assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed()); } - @Test - public void testStandbyBucketDelay_workingSet() throws Exception { - setQuotasEnabled(false); - setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); - setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); - assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); - - when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), - anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); - - mNowElapsedTest = mTestTimer.getElapsed(); - mTestTimer.expire(); - - verify(mUsageStatsManagerInternal, atLeastOnce()) - .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), - eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); - final long expectedNextTrigger = mNowElapsedTest - + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_WORKING_SET); - assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); - } - - @Test - public void testStandbyBucketDelay_frequent() throws Exception { - setQuotasEnabled(false); - setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); - setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); - assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); - - when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), - anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); - mNowElapsedTest = mTestTimer.getElapsed(); - mTestTimer.expire(); - - verify(mUsageStatsManagerInternal, atLeastOnce()) - .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), - eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); - final long expectedNextTrigger = mNowElapsedTest - + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_FREQUENT); - assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed()); - } - - @Test - public void testStandbyBucketDelay_rare() throws Exception { - setQuotasEnabled(false); - setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); - setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); - assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); - - when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), - anyLong())).thenReturn(STANDBY_BUCKET_RARE); - mNowElapsedTest = mTestTimer.getElapsed(); - mTestTimer.expire(); - - verify(mUsageStatsManagerInternal, atLeastOnce()) - .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), - eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); - final long expectedNextTrigger = mNowElapsedTest - + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_RARE); - assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed()); - } - private void testQuotasDeferralOnSet(int standbyBucket) throws Exception { final int quota = mService.getQuotaForBucketLocked(standbyBucket); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), @@ -601,73 +537,61 @@ public class AlarmManagerServiceTest { @Test public void testActiveQuota_deferredOnSet() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE); } @Test public void testActiveQuota_deferredOnExpiration() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE); } @Test public void testActiveQuota_notDeferred() throws Exception { - setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_ACTIVE); } @Test public void testWorkingQuota_deferredOnSet() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET); } @Test public void testWorkingQuota_deferredOnExpiration() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET); } @Test public void testWorkingQuota_notDeferred() throws Exception { - setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET); } @Test public void testFrequentQuota_deferredOnSet() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT); } @Test public void testFrequentQuota_deferredOnExpiration() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT); } @Test public void testFrequentQuota_notDeferred() throws Exception { - setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_FREQUENT); } @Test public void testRareQuota_deferredOnSet() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_RARE); } @Test public void testRareQuota_deferredOnExpiration() throws Exception { - setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE); } @Test public void testRareQuota_notDeferred() throws Exception { - setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_RARE); } @@ -686,7 +610,6 @@ public class AlarmManagerServiceTest { @Test public void testQuotaDowngrade() throws Exception { - setQuotasEnabled(true); final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); @@ -714,7 +637,6 @@ public class AlarmManagerServiceTest { @Test public void testQuotaUpgrade() throws Exception { - setQuotasEnabled(true); final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); @@ -752,7 +674,6 @@ public class AlarmManagerServiceTest { @Test public void testCharging() throws Exception { - setQuotasEnabled(true); final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java index 1f4656ae54a4..1e270077780d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java @@ -513,7 +513,8 @@ public class AppStateTrackerTest { mIUidObserver.onUidStateChanged(UID_2, - ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0); + ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); waitUntilMainHandlerDrain(); assertTrue(instance.isUidActive(UID_1)); @@ -530,7 +531,8 @@ public class AppStateTrackerTest { mIUidObserver.onUidStateChanged(UID_1, - ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0); + ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); waitUntilMainHandlerDrain(); assertTrue(instance.isUidActive(UID_1)); @@ -564,7 +566,8 @@ public class AppStateTrackerTest { assertTrue(instance.isUidInForeground(Process.SYSTEM_UID)); mIUidObserver.onUidStateChanged(UID_1, - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0); + ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); waitUntilMainHandlerDrain(); assertFalse(instance.isUidActive(UID_1)); @@ -576,7 +579,8 @@ public class AppStateTrackerTest { assertTrue(instance.isUidInForeground(Process.SYSTEM_UID)); mIUidObserver.onUidStateChanged(UID_1, - ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0); + ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); waitUntilMainHandlerDrain(); assertFalse(instance.isUidActive(UID_1)); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 6dd1bd87019f..57f55e32a381 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -23,7 +23,6 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT; import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; -import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; import static android.app.ActivityManager.PROCESS_STATE_HOME; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; @@ -368,7 +367,7 @@ public class MockingOomAdjusterTests { sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE); - assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION, PERCEPTIBLE_APP_ADJ, + assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, SCHED_GROUP_DEFAULT); } diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java index b6a7b09b3b7f..fa209a7a5f8e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java @@ -16,7 +16,6 @@ package com.android.server.appop; import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; -import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.MODE_FOREGROUND; @@ -338,18 +337,22 @@ public class AppOpsServiceTest { public void testUidProcStateChange_cachedToTopToCached() throws Exception { setupProcStateTests(); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP, + ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); // Second time to make sure that settle time is overcome Thread.sleep(50); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); } @@ -357,12 +360,13 @@ public class AppOpsServiceTest { @Test public void testUidProcStateChange_cachedToFgs() { setupProcStateTests(); - - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); } @@ -371,12 +375,13 @@ public class AppOpsServiceTest { public void testUidProcStateChange_cachedToFgsLocation() { setupProcStateTests(); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, - PROCESS_STATE_FOREGROUND_SERVICE_LOCATION); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isEqualTo(MODE_ALLOWED); } @@ -385,18 +390,22 @@ public class AppOpsServiceTest { public void testUidProcStateChange_topToFgs() throws Exception { setupProcStateTests(); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP, + ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_NONE); // Second time to make sure that settle time is overcome Thread.sleep(50); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); } @@ -405,25 +414,31 @@ public class AppOpsServiceTest { public void testUidProcStateChange_topToFgsLocationToFgs() throws Exception { setupProcStateTests(); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP); + mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP, + ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION); // Second time to make sure that settle time is overcome Thread.sleep(50); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isEqualTo(MODE_ALLOWED); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_NONE); // Second time to make sure that settle time is overcome Thread.sleep(50); - mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE); + mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE, + ActivityManager.PROCESS_CAPABILITY_NONE); assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null)) .isNotEqualTo(MODE_ALLOWED); } diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java index 8863d5abeca3..5bd08c03d233 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java @@ -233,7 +233,8 @@ public class QuotaControllerTest { doReturn(procState).when(mActivityMangerInternal).getUidProcessState(uid); SparseBooleanArray foregroundUids = mQuotaController.getForegroundUids(); spyOn(foregroundUids); - mUidObserver.onUidStateChanged(uid, procState, 0); + mUidObserver.onUidStateChanged(uid, procState, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { verify(foregroundUids, timeout(2 * SECOND_IN_MILLIS).times(1)) .put(eq(uid), eq(true)); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java index 1edc9534b011..49412bc0c559 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -571,7 +571,8 @@ public class ActivityManagerServiceTest { verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, (observer, changeItem) -> { verify(observer).onUidStateChanged(changeItem.uid, - changeItem.processState, changeItem.procStateSeq); + changeItem.processState, changeItem.procStateSeq, + ActivityManager.PROCESS_CAPABILITY_NONE); }); } // Verify there are no other callbacks for this observer. @@ -619,7 +620,8 @@ public class ActivityManagerServiceTest { // First process state message is always delivered regardless of whether the process state // change is above or below the cutpoint (PROCESS_STATE_SERVICE). verify(observer).onUidStateChanged(TEST_UID, - changeItem.processState, changeItem.procStateSeq); + changeItem.processState, changeItem.procStateSeq, + ActivityManager.PROCESS_CAPABILITY_NONE); verifyNoMoreInteractions(observer); changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER; @@ -636,7 +638,8 @@ public class ActivityManagerServiceTest { // the current process state change is above cutpoint, so callback will be invoked with the // current process state change. verify(observer).onUidStateChanged(TEST_UID, - changeItem.processState, changeItem.procStateSeq); + changeItem.processState, changeItem.procStateSeq, + ActivityManager.PROCESS_CAPABILITY_NONE); verifyNoMoreInteractions(observer); changeItem.processState = ActivityManager.PROCESS_STATE_TOP; @@ -653,7 +656,8 @@ public class ActivityManagerServiceTest { // the current process state change is below cutpoint, so callback will be invoked with the // current process state change. verify(observer).onUidStateChanged(TEST_UID, - changeItem.processState, changeItem.procStateSeq); + changeItem.processState, changeItem.procStateSeq, + ActivityManager.PROCESS_CAPABILITY_NONE); verifyNoMoreInteractions(observer); } diff --git a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java index d3bcff528155..d12d8040183a 100644 --- a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java @@ -181,7 +181,7 @@ public class OomAdjusterTests { @Test public void testMaybeUpdateUsageStats_ProcStateFGSLocation() { final long elapsedTime = ZERO; - mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION); + mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); assertProcessRecordState(elapsedTime, false, ZERO); diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 64bd2c7a4095..51bae166b2dc 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -1362,7 +1362,8 @@ public class NetworkPolicyManagerServiceTest { private void callOnUidStateChanged(int uid, int procState, long procStateSeq) throws Exception { - mUidObserver.onUidStateChanged(uid, procState, procStateSeq); + mUidObserver.onUidStateChanged(uid, procState, procStateSeq, + ActivityManager.PROCESS_CAPABILITY_NONE); final CountDownLatch latch = new CountDownLatch(1); mService.mUidEventHandler.post(() -> { latch.countDown(); diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index b806180a8584..f9fc3a145953 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -2222,7 +2222,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected void makeUidForeground(int uid) { try { mService.mUidObserver.onUidStateChanged( - uid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0); + uid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } @@ -2235,7 +2236,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected void makeUidBackground(int uid) { try { mService.mUidObserver.onUidStateChanged( - uid, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0); + uid, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index fd3678dae0c4..7b101c728d0f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -1647,7 +1647,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { // State changed, but not foreground, so no resetting. mService.mUidObserver.onUidStateChanged( - CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0); + CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); }); @@ -1671,7 +1672,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { // State changed, package1 foreground, reset. mService.mUidObserver.onUidStateChanged( - CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0); + CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertEquals(3, mManager.getRemainingCallCount()); }); @@ -1691,16 +1693,19 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); }); mService.mUidObserver.onUidStateChanged( - CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0); + CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); mInjectedCurrentTimeMillis++; // Different app comes to foreground briefly, and goes back to background. // Now, make sure package 2's counter is reset, even in this case. mService.mUidObserver.onUidStateChanged( - CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0); + CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); mService.mUidObserver.onUidStateChanged( - CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0); + CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertEquals(3, mManager.getRemainingCallCount()); @@ -1731,9 +1736,11 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { }); mService.mUidObserver.onUidStateChanged( - CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0); + CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); mService.mUidObserver.onUidStateChanged( - CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0); + CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertEquals(3, mManager.getRemainingCallCount()); @@ -1760,7 +1767,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { // Now, also try calling some APIs and make sure foreground apps don't get throttled. mService.mUidObserver.onUidStateChanged( UserHandle.getUid(USER_10, CALLING_UID_1), - ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0); + ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertEquals(3, mManager.getRemainingCallCount()); assertFalse(mManager.isRateLimitingActive()); diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java index 0196279cbf56..f08044c0b5b5 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -691,35 +691,16 @@ public class DexManagerTests { } } - private boolean shouldPackageRunOob( - boolean isDefaultEnabled, String defaultWhitelist, String overrideEnabled, - String overrideWhitelist, Collection<String> packageNamesInSameProcess) { + private boolean shouldPackageRunOob(boolean isDefaultEnabled, String whitelist, + Collection<String> packageNamesInSameProcess) { return DexManager.isPackageSelectedToRunOobInternal( - isDefaultEnabled, defaultWhitelist, overrideEnabled, overrideWhitelist, - packageNamesInSameProcess); + isDefaultEnabled, whitelist, packageNamesInSameProcess); } @Test - public void testOobPackageSelectionSwitch() { + public void testOobPackageSelectionDefault() { // Feature is off by default, not overriden - assertFalse(shouldPackageRunOob(false, "ALL", null, null, null)); - - // Feature is off by default, overriden - assertTrue(shouldPackageRunOob(false, "ALL", "true", "ALL", null)); - assertFalse(shouldPackageRunOob(false, "ALL", "false", null, null)); - assertFalse(shouldPackageRunOob(false, "ALL", "false", "ALL", null)); - assertFalse(shouldPackageRunOob(false, "ALL", "false", null, null)); - - // Feature is on by default, not overriden - assertTrue(shouldPackageRunOob(true, "ALL", null, null, null)); - assertTrue(shouldPackageRunOob(true, "ALL", null, null, null)); - assertTrue(shouldPackageRunOob(true, "ALL", null, "ALL", null)); - - // Feature is on by default, overriden - assertTrue(shouldPackageRunOob(true, "ALL", "true", null, null)); - assertTrue(shouldPackageRunOob(true, "ALL", "true", "ALL", null)); - assertFalse(shouldPackageRunOob(true, "ALL", "false", null, null)); - assertFalse(shouldPackageRunOob(true, "ALL", "false", "ALL", null)); + assertFalse(shouldPackageRunOob(false, "ALL", null)); } @Test @@ -734,24 +715,19 @@ public class DexManagerTests { final Collection<String> runningPackages = Arrays.asList("com.priv.app1", "com.priv.app2"); // Feature is off, whitelist does not matter - assertFalse(shouldPackageRunOob(false, kWhitelistApp0, null, null, runningPackages)); - assertFalse(shouldPackageRunOob(false, kWhitelistApp1, null, null, runningPackages)); - assertFalse(shouldPackageRunOob(false, "", null, kWhitelistApp1, runningPackages)); - assertFalse(shouldPackageRunOob(false, "", null, "ALL", runningPackages)); - assertFalse(shouldPackageRunOob(false, "ALL", null, "ALL", runningPackages)); - assertFalse(shouldPackageRunOob(false, "ALL", null, "", runningPackages)); - - // Feature is on, app not in default or overridden whitelist - assertFalse(shouldPackageRunOob(true, kWhitelistApp0, null, null, runningPackages)); - assertFalse(shouldPackageRunOob(true, "", null, kWhitelistApp0, runningPackages)); - assertFalse(shouldPackageRunOob(true, "ALL", null, kWhitelistApp0, runningPackages)); - - // Feature is on, app in default or overridden whitelist - assertTrue(shouldPackageRunOob(true, kWhitelistApp1, null, null, runningPackages)); - assertTrue(shouldPackageRunOob(true, kWhitelistApp2, null, null, runningPackages)); - assertTrue(shouldPackageRunOob(true, kWhitelistApp1AndApp2, null, null, runningPackages)); - assertTrue(shouldPackageRunOob(true, kWhitelistApp1, null, "ALL", runningPackages)); - assertTrue(shouldPackageRunOob(true, "", null, kWhitelistApp1, runningPackages)); - assertTrue(shouldPackageRunOob(true, "ALL", null, kWhitelistApp1, runningPackages)); + assertFalse(shouldPackageRunOob(false, kWhitelistApp0, runningPackages)); + assertFalse(shouldPackageRunOob(false, kWhitelistApp1, runningPackages)); + assertFalse(shouldPackageRunOob(false, "", runningPackages)); + assertFalse(shouldPackageRunOob(false, "ALL", runningPackages)); + + // Feature is on, app not in whitelist + assertFalse(shouldPackageRunOob(true, kWhitelistApp0, runningPackages)); + assertFalse(shouldPackageRunOob(true, "", runningPackages)); + + // Feature is on, app in whitelist + assertTrue(shouldPackageRunOob(true, kWhitelistApp1, runningPackages)); + assertTrue(shouldPackageRunOob(true, kWhitelistApp2, runningPackages)); + assertTrue(shouldPackageRunOob(true, kWhitelistApp1AndApp2, runningPackages)); + assertTrue(shouldPackageRunOob(true, "ALL", runningPackages)); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java index 77f9f0428e70..b6eaab7efec4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -69,8 +70,8 @@ public class AnimatingActivityRegistryTest extends WindowTestsBase { activity1.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */); activity2.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */); - assertTrue(activity1.isSelfAnimating()); - assertTrue(activity2.isSelfAnimating()); + assertTrue(activity1.isAnimating(TRANSITION)); + assertTrue(activity2.isAnimating(TRANSITION)); // Make sure that first animation finish is deferred, second one is not deferred, and first // one gets cancelled. @@ -92,8 +93,8 @@ public class AnimatingActivityRegistryTest extends WindowTestsBase { window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */); window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */); - assertTrue(window1.isSelfAnimating()); - assertTrue(window2.isSelfAnimating()); + assertTrue(window1.isAnimating(TRANSITION)); + assertTrue(window2.isAnimating(TRANSITION)); // Make sure that first animation finish is deferred, and removing the second window stops // finishes all pending deferred finishings. diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java index 06afce2368b7..5f42d2398421 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java @@ -147,8 +147,8 @@ public class AppTransitionTests extends WindowTestsBase { // Make sure each display is in animating stage. assertTrue(dc1.mOpeningApps.size() > 0); assertTrue(dc2.mClosingApps.size() > 0); - assertTrue(dc1.isAppAnimating()); - assertTrue(dc2.isAppAnimating()); + assertTrue(dc1.isAppTransitioning()); + assertTrue(dc2.isAppTransitioning()); } @Test @@ -219,10 +219,10 @@ public class AppTransitionTests extends WindowTestsBase { assertTrue(dc.mClosingApps.size() > 0); // Make sure window is in animating stage before freeze, and cancel after freeze. - assertTrue(dc.isAppAnimating()); + assertTrue(dc.isAppTransitioning()); assertFalse(runner.mCancelled); dc.mAppTransition.freeze(); - assertFalse(dc.isAppAnimating()); + assertFalse(dc.isAppTransitioning()); assertTrue(runner.mCancelled); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java index 2fc03c7f13d3..164d28d57cb0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java @@ -23,12 +23,13 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import android.graphics.Rect; @@ -141,7 +142,7 @@ public class TaskStackTests extends WindowTestsBase { final Task task = createTaskInStack(stack, 0 /* userId */); // Stack removal is deferred if one of its child is animating. - doReturn(true).when(task).isSelfAnimating(); + doReturn(true).when(task).isAnimating(TRANSITION | CHILDREN); stack.removeIfPossible(); // For the case of deferred removal the task controller will still be connected to the its diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index 85aff7f9a9cd..853644873f01 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -24,13 +24,18 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; +import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; +import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -335,7 +340,53 @@ public class WindowContainerTests extends WindowTestsBase { } @Test - public void testIsAnimating() { + public void testIsAnimating_TransitionFlag() { + final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm); + final TestWindowContainer root = builder.setLayer(0).build(); + final TestWindowContainer child1 = root.addChildWindow( + builder.setWaitForTransitionStart(true)); + + assertFalse(root.isAnimating(TRANSITION)); + assertTrue(child1.isAnimating(TRANSITION)); + } + + @Test + public void testIsAnimating_ParentsFlag() { + final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm); + final TestWindowContainer root = builder.setLayer(0).build(); + final TestWindowContainer child1 = root.addChildWindow(builder); + final TestWindowContainer child2 = root.addChildWindow(builder.setIsAnimating(true)); + final TestWindowContainer child21 = child2.addChildWindow(builder.setIsAnimating(false)); + + assertFalse(root.isAnimating()); + assertFalse(child1.isAnimating()); + assertFalse(child1.isAnimating(PARENTS)); + assertTrue(child2.isAnimating()); + assertTrue(child2.isAnimating(PARENTS)); + assertFalse(child21.isAnimating()); + assertTrue(child21.isAnimating(PARENTS)); + } + + @Test + public void testIsAnimating_ChildrenFlag() { + final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm); + final TestWindowContainer root = builder.setLayer(0).build(); + final TestWindowContainer child1 = root.addChildWindow(builder); + final TestWindowContainer child2 = root.addChildWindow(builder.setIsAnimating(true)); + final TestWindowContainer child11 = child1.addChildWindow(builder.setIsAnimating(true)); + + assertFalse(root.isAnimating()); + assertTrue(root.isAnimating(CHILDREN)); + assertFalse(child1.isAnimating()); + assertTrue(child1.isAnimating(CHILDREN)); + assertTrue(child2.isAnimating()); + assertTrue(child2.isAnimating(CHILDREN)); + assertTrue(child11.isAnimating()); + assertTrue(child11.isAnimating(CHILDREN)); + } + + @Test + public void testIsAnimating_combineFlags() { final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm); final TestWindowContainer root = builder.setLayer(0).build(); @@ -345,19 +396,19 @@ public class WindowContainerTests extends WindowTestsBase { final TestWindowContainer child12 = child1.addChildWindow(builder.setIsAnimating(true)); final TestWindowContainer child21 = child2.addChildWindow(); - assertFalse(root.isAnimating()); - assertTrue(child1.isAnimating()); - assertTrue(child11.isAnimating()); - assertTrue(child12.isAnimating()); - assertFalse(child2.isAnimating()); - assertFalse(child21.isAnimating()); - - assertTrue(root.isSelfOrChildAnimating()); - assertTrue(child1.isSelfOrChildAnimating()); - assertFalse(child11.isSelfOrChildAnimating()); - assertTrue(child12.isSelfOrChildAnimating()); - assertFalse(child2.isSelfOrChildAnimating()); - assertFalse(child21.isSelfOrChildAnimating()); + assertFalse(root.isAnimating(TRANSITION | PARENTS)); + assertTrue(child1.isAnimating(TRANSITION | PARENTS)); + assertTrue(child11.isAnimating(TRANSITION | PARENTS)); + assertTrue(child12.isAnimating(TRANSITION | PARENTS)); + assertFalse(child2.isAnimating(TRANSITION | PARENTS)); + assertFalse(child21.isAnimating(TRANSITION | PARENTS)); + + assertTrue(root.isAnimating(TRANSITION | CHILDREN)); + assertTrue(child1.isAnimating(TRANSITION | CHILDREN)); + assertFalse(child11.isAnimating(TRANSITION | CHILDREN)); + assertTrue(child12.isAnimating(TRANSITION | CHILDREN)); + assertFalse(child2.isAnimating(TRANSITION | CHILDREN)); + assertFalse(child21.isAnimating(TRANSITION | CHILDREN)); } @Test @@ -716,6 +767,7 @@ public class WindowContainerTests extends WindowTestsBase { private boolean mIsAnimating; private boolean mIsVisible; private boolean mFillsParent; + private boolean mWaitForTransitStart; private Integer mOrientation; private boolean mOnParentChangedCalled; @@ -738,7 +790,7 @@ public class WindowContainerTests extends WindowTestsBase { }; TestWindowContainer(WindowManagerService wm, int layer, boolean isAnimating, - boolean isVisible, Integer orientation) { + boolean isVisible, boolean waitTransitStart, Integer orientation) { super(wm); mLayer = layer; @@ -746,6 +798,9 @@ public class WindowContainerTests extends WindowTestsBase { mIsVisible = isVisible; mFillsParent = true; mOrientation = orientation; + mWaitForTransitStart = waitTransitStart; + spyOn(mSurfaceAnimator); + doReturn(mIsAnimating).when(mSurfaceAnimator).isAnimating(); } TestWindowContainer getParentWindow() { @@ -783,11 +838,6 @@ public class WindowContainerTests extends WindowTestsBase { } @Override - boolean isSelfAnimating() { - return mIsAnimating; - } - - @Override boolean isVisible() { return mIsVisible; } @@ -810,6 +860,11 @@ public class WindowContainerTests extends WindowTestsBase { void setFillsParent(boolean fillsParent) { mFillsParent = fillsParent; } + + @Override + boolean isWaitingForTransitionStart() { + return mWaitForTransitStart; + } } private static class TestWindowContainerBuilder { @@ -817,6 +872,7 @@ public class WindowContainerTests extends WindowTestsBase { private int mLayer; private boolean mIsAnimating; private boolean mIsVisible; + private boolean mIsWaitTransitStart; private Integer mOrientation; TestWindowContainerBuilder(WindowManagerService wm) { @@ -847,8 +903,14 @@ public class WindowContainerTests extends WindowTestsBase { return this; } + TestWindowContainerBuilder setWaitForTransitionStart(boolean waitTransitStart) { + mIsWaitTransitStart = waitTransitStart; + return this; + } + TestWindowContainer build() { - return new TestWindowContainer(mWm, mLayer, mIsAnimating, mIsVisible, mOrientation); + return new TestWindowContainer(mWm, mLayer, mIsAnimating, mIsVisible, + mIsWaitTransitStart, mOrientation); } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 6a805683e23d..f9b365906c5b 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -400,7 +400,7 @@ public class UsageStatsService extends SystemService implements private final IUidObserver mUidObserver = new IUidObserver.Stub() { @Override - public void onUidStateChanged(int uid, int procState, long procStateSeq) { + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget(); } @@ -411,7 +411,8 @@ public class UsageStatsService extends SystemService implements @Override public void onUidGone(int uid, boolean disabled) { - onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0); + onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0, + ActivityManager.PROCESS_CAPABILITY_NONE); } @Override diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index fa16b84b544c..20abe773e415 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -858,7 +858,7 @@ public abstract class Connection extends Conferenceable { } /** @hide */ - public abstract static class Listener { + abstract static class Listener { public void onStateChanged(Connection c, int state) {} public void onAddressChanged(Connection c, Uri newAddress, int presentation) {} public void onCallerDisplayNameChanged( @@ -2006,7 +2006,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final Connection addConnectionListener(Listener l) { + final Connection addConnectionListener(Listener l) { mListeners.add(l); return this; } @@ -2019,7 +2019,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final Connection removeConnectionListener(Listener l) { + final Connection removeConnectionListener(Listener l) { if (l != null) { mListeners.remove(l); } diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java index 46eb9df8bdad..60281ad11f60 100644 --- a/telephony/java/android/telephony/CellBroadcastService.java +++ b/telephony/java/android/telephony/CellBroadcastService.java @@ -17,12 +17,18 @@ package android.telephony; import android.annotation.CallSuper; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; +import android.os.Bundle; import android.os.IBinder; +import android.os.RemoteCallback; import android.telephony.cdma.CdmaSmsCbProgramData; +import java.util.List; +import java.util.function.Consumer; + /** * A service which exposes the cell broadcast handling module to the system. * <p> @@ -46,6 +52,7 @@ import android.telephony.cdma.CdmaSmsCbProgramData; * </service> * </manifest> * }</pre> + * * @hide */ @SystemApi @@ -62,21 +69,38 @@ public abstract class CellBroadcastService extends Service { /** * Handle a GSM cell broadcast SMS message forwarded from the system. + * * @param slotIndex the index of the slot which received the message - * @param message the SMS PDU + * @param message the SMS PDU */ public abstract void onGsmCellBroadcastSms(int slotIndex, byte[] message); /** * Handle a CDMA cell broadcast SMS message forwarded from the system. - * @param slotIndex the index of the slot which received the message - * @param bearerData the CDMA SMS bearer data + * + * @param slotIndex the index of the slot which received the message + * @param bearerData the CDMA SMS bearer data * @param serviceCategory the CDMA SCPT service category */ public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] bearerData, @CdmaSmsCbProgramData.Category int serviceCategory); /** + * Handle a CDMA cell broadcast SMS message forwarded from the system. + * + * @param slotIndex the index of the slot which received the message + * @param smsCbProgramData the SMS CB program data of the message + * @param originatingAddress the originating address of the message, as a non-separated dial + * string + * @param callback a callback to run after each cell broadcast receiver has handled + * the SCP message. The bundle will contain a non-separated + * dial string as and an ArrayList of {@link CdmaSmsCbProgramResults}. + */ + public abstract void onCdmaScpMessage(int slotIndex, + @NonNull List<CdmaSmsCbProgramData> smsCbProgramData, + @NonNull String originatingAddress, @NonNull Consumer<Bundle> callback); + + /** * If overriding this method, call through to the super method for any unknown actions. * {@inheritDoc} */ @@ -89,13 +113,15 @@ public abstract class CellBroadcastService extends Service { /** * A wrapper around ICellBroadcastService that forwards calls to implementations of * {@link CellBroadcastService}. + * * @hide */ public class ICellBroadcastServiceWrapper extends ICellBroadcastService.Stub { /** * Handle a GSM cell broadcast SMS. + * * @param slotIndex the index of the slot which received the broadcast - * @param message the SMS message PDU + * @param message the SMS message PDU */ @Override public void handleGsmCellBroadcastSms(int slotIndex, byte[] message) { @@ -104,8 +130,9 @@ public abstract class CellBroadcastService extends Service { /** * Handle a CDMA cell broadcast SMS. - * @param slotIndex the index of the slot which received the broadcast - * @param bearerData the CDMA SMS bearer data + * + * @param slotIndex the index of the slot which received the broadcast + * @param bearerData the CDMA SMS bearer data * @param serviceCategory the CDMA SCPT service category */ @Override @@ -114,5 +141,25 @@ public abstract class CellBroadcastService extends Service { CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, bearerData, serviceCategory); } + + /** + * Handle a CDMA Service Category Program message. + * + * @param slotIndex the index of the slot which received the message + * @param smsCbProgramData the SMS CB program data of the message + * @param originatingAddress the originating address of the message + * @param callback a callback to run after each cell broadcast receiver has + * handled the SCP message + */ + @Override + public void handleCdmaScpMessage(int slotIndex, + List<CdmaSmsCbProgramData> smsCbProgramData, String originatingAddress, + RemoteCallback callback) { + Consumer<Bundle> consumer = bundle -> { + callback.sendResult(bundle); + }; + CellBroadcastService.this.onCdmaScpMessage(slotIndex, smsCbProgramData, + originatingAddress, consumer); + } } } diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java index 1912c60ac122..f9b7f6dbc193 100644 --- a/telephony/java/android/telephony/CellSignalStrengthNr.java +++ b/telephony/java/android/telephony/CellSignalStrengthNr.java @@ -194,13 +194,13 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa /** @hide */ @Override public void updateLevel(PersistableBundle cc, ServiceState ss) { - if (mCsiRsrp == CellInfo.UNAVAILABLE) { + if (mSsRsrp == CellInfo.UNAVAILABLE) { mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; - } else if (mCsiRsrp >= SIGNAL_GREAT_THRESHOLD) { + } else if (mSsRsrp >= SIGNAL_GREAT_THRESHOLD) { mLevel = SIGNAL_STRENGTH_GREAT; - } else if (mCsiRsrp >= SIGNAL_GOOD_THRESHOLD) { + } else if (mSsRsrp >= SIGNAL_GOOD_THRESHOLD) { mLevel = SIGNAL_STRENGTH_GOOD; - } else if (mCsiRsrp >= SIGNAL_MODERATE_THRESHOLD) { + } else if (mSsRsrp >= SIGNAL_MODERATE_THRESHOLD) { mLevel = SIGNAL_STRENGTH_MODERATE; } else { mLevel = SIGNAL_STRENGTH_POOR; @@ -212,7 +212,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa * * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 * - * @return RSCP in ASU 0..97, 255, or UNAVAILABLE + * @return RSRP in ASU 0..97, 255, or UNAVAILABLE */ @Override public int getAsuLevel() { @@ -231,11 +231,11 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa } /** - * Get the CSI-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. + * Get the SS-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. */ @Override public int getDbm() { - return mCsiRsrp; + return mSsRsrp; } /** @hide */ diff --git a/telephony/java/android/telephony/ICellBroadcastService.aidl b/telephony/java/android/telephony/ICellBroadcastService.aidl index bcd6cc546eed..11263d99cb8f 100644 --- a/telephony/java/android/telephony/ICellBroadcastService.aidl +++ b/telephony/java/android/telephony/ICellBroadcastService.aidl @@ -16,6 +16,9 @@ package android.telephony; +import android.os.RemoteCallback; +import android.telephony.cdma.CdmaSmsCbProgramData; + /** * Service bound to by the system to allow custom handling of cell broadcast messages. * <p> @@ -29,4 +32,8 @@ interface ICellBroadcastService { /** @see android.telephony.CellBroadcastService#onCdmaCellBroadcastSms */ oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] bearerData, int serviceCategory); + + /** @see android.telephony.CellBroadcastService#onCdmaScpMessage */ + oneway void handleCdmaScpMessage(int slotId, in List<CdmaSmsCbProgramData> programData, + String originatingAddress, in RemoteCallback callback); } diff --git a/telephony/java/android/telephony/ImsiEncryptionInfo.java b/telephony/java/android/telephony/ImsiEncryptionInfo.java index ef2f121ba01b..75a79d62d2aa 100644 --- a/telephony/java/android/telephony/ImsiEncryptionInfo.java +++ b/telephony/java/android/telephony/ImsiEncryptionInfo.java @@ -15,9 +15,11 @@ */ package android.telephony; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import java.util.Date; import android.util.Log; import java.security.KeyFactory; @@ -25,18 +27,18 @@ import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; +import java.util.Date; /** * Class to represent information sent by the carrier, which will be used to encrypt * the IMSI + IMPI. The ecryption is being done by WLAN, and the modem. - * * @hide */ +@SystemApi public final class ImsiEncryptionInfo implements Parcelable { private static final String LOG_TAG = "ImsiEncryptionInfo"; - private final String mcc; private final String mnc; private final PublicKey publicKey; @@ -45,11 +47,13 @@ public final class ImsiEncryptionInfo implements Parcelable { //Date-Time in UTC when the key will expire. private final Date expirationTime; + /** @hide */ public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, byte[] key, Date expirationTime) { this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime); } + /** @hide */ public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, PublicKey publicKey, Date expirationTime) { // todo need to validate that ImsiEncryptionInfo is being created with the correct params. @@ -63,6 +67,7 @@ public final class ImsiEncryptionInfo implements Parcelable { this.expirationTime = expirationTime; } + /** @hide */ public ImsiEncryptionInfo(Parcel in) { int length = in.readInt(); byte b[] = new byte[length]; @@ -75,26 +80,40 @@ public final class ImsiEncryptionInfo implements Parcelable { expirationTime = new Date(in.readLong()); } + /** @hide */ public String getMnc() { return this.mnc; } + /** @hide */ public String getMcc() { return this.mcc; } + /** + * Returns key identifier, a string that helps the authentication server to locate the + * private key to decrypt the permanent identity, or {@code null} when uavailable. + */ + @Nullable public String getKeyIdentifier() { return this.keyIdentifier; } + /** @hide */ public int getKeyType() { return this.keyType; } + /** + * Returns the carrier public key that is used for the IMSI encryption, + * or {@code null} when uavailable. + */ + @Nullable public PublicKey getPublicKey() { return this.publicKey; } + /** @hide */ public Date getExpirationTime() { return this.expirationTime; } @@ -115,7 +134,7 @@ public final class ImsiEncryptionInfo implements Parcelable { return 0; } - public static final @android.annotation.NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR = + public static final @NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR = new Parcelable.Creator<ImsiEncryptionInfo>() { @Override public ImsiEncryptionInfo createFromParcel(Parcel in) { @@ -129,7 +148,7 @@ public final class ImsiEncryptionInfo implements Parcelable { }; @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { byte[] b = publicKey.getEncoded(); dest.writeInt(b.length); dest.writeByteArray(b); diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index ee291fa0122b..2c16110ceb4c 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -2669,4 +2669,74 @@ public final class SmsManager { } return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE; } + + /** + * Gets the SMSC address from (U)SIM. + * + * <p class="note"><strong>Note:</strong> Using this method requires that your app is the + * default SMS application, or READ_PRIVILEGED_PHONE_STATE permission, or has the carrier + * privileges.</p> + * + * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation + * dialog. If this method is called on a device that has multiple active subscriptions, this + * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined + * default subscription is defined, the subscription ID associated with this method will be + * INVALID, which will result in the operation being completed on the subscription associated + * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation + * is performed on the correct subscription. + * </p> + * + * @return the SMSC address string, null if failed. + */ + @SuppressAutoDoc // for carrier privileges and default SMS application. + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @Nullable + public String getSmscAddress() { + String smsc = null; + + try { + ISms iSms = getISmsService(); + if (iSms != null) { + smsc = iSms.getSmscAddressFromIccEfForSubscriber( + getSubscriptionId(), ActivityThread.currentPackageName()); + } + } catch (RemoteException ex) { + // ignore it + } + return smsc; + } + + /** + * Sets the SMSC address on (U)SIM. + * + * <p class="note"><strong>Note:</strong> Using this method requires that your app is the + * default SMS application, or has {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * permission, or has the carrier privileges.</p> + * + * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation + * dialog. If this method is called on a device that has multiple active subscriptions, this + * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined + * default subscription is defined, the subscription ID associated with this method will be + * INVALID, which will result in the operation being completed on the subscription associated + * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation + * is performed on the correct subscription. + * </p> + * + * @param smsc the SMSC address string. + * @return true for success, false otherwise. + */ + @SuppressAutoDoc // for carrier privileges and default SMS application. + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public boolean setSmscAddress(@NonNull String smsc) { + try { + ISms iSms = getISmsService(); + if (iSms != null) { + return iSms.setSmscAddressOnIccEfForSubscriber( + smsc, getSubscriptionId(), ActivityThread.currentPackageName()); + } + } catch (RemoteException ex) { + // ignore it + } + return false; + } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 8455e3d57e49..3c22a07a8ea3 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -197,12 +197,29 @@ public class TelephonyManager { /** @hide */ static public final int OTASP_SIM_UNPROVISIONED = 5; - /** @hide */ + /** + * Used in carrier Wi-Fi for IMSI + IMPI encryption, this indicates a public key that's + * available for use in ePDG links. + * + * @hide + */ + @SystemApi static public final int KEY_TYPE_EPDG = 1; - /** @hide */ + /** + * Used in carrier Wi-Fi for IMSI + IMPI encryption, this indicates a public key that's + * available for use in WLAN links. + * + * @hide + */ + @SystemApi static public final int KEY_TYPE_WLAN = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"KEY_TYPE_"}, value = {KEY_TYPE_EPDG, KEY_TYPE_WLAN}) + public @interface KeyType {} + /** * No Single Radio Voice Call Continuity (SRVCC) handover is active. * See TS 23.216 for more information. @@ -3874,25 +3891,27 @@ public class TelephonyManager { } /** - * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI. - * This includes the public key and the key identifier. For multi-sim devices, if no subId - * has been specified, we will return the value for the dafault data sim. - * Return null if it is unavailable. + * Returns carrier specific information that will be used to encrypt the IMSI and IMPI, + * including the public key and the key identifier; or {@code null} if not available. * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - * @param keyType whether the key is being used for wlan or epdg. Valid key types are - * {@link TelephonyManager#KEY_TYPE_EPDG} or - * {@link TelephonyManager#KEY_TYPE_WLAN}. + * For a multi-sim device, the dafault data sim is used if not specified. + * <p> + * Requires Permission: READ_PRIVILEGED_PHONE_STATE. + * + * @param keyType whether the key is being used for EPDG or WLAN. Valid values are + * {@link #KEY_TYPE_EPDG} or {@link #KEY_TYPE_WLAN}. * @return ImsiEncryptionInfo Carrier specific information that will be used to encrypt the * IMSI and IMPI. This includes the public key and the key identifier. This information - * will be stored in the device keystore. The system will return a null when no key was - * found, and the carrier does not require a key. The system will throw - * IllegalArgumentException when an invalid key is sent or when key is required but + * will be stored in the device keystore. {@code null} will be returned when no key is + * found, and the carrier does not require a key. + * @throws IllegalArgumentException when an invalid key is found or when key is required but * not found. * @hide */ - public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) { + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + @Nullable + public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(@KeyType int keyType) { try { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) { @@ -3920,14 +3939,21 @@ public class TelephonyManager { } /** - * Resets the Carrier Keys in the database. This involves 2 steps: + * Resets the carrier keys used to encrypt the IMSI and IMPI. + * <p> + * This involves 2 steps: * 1. Delete the keys from the database. * 2. Send an intent to download new Certificates. * <p> - * Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * For a multi-sim device, the dafault data sim is used if not specified. + * <p> + * Requires Permission: MODIFY_PHONE_STATE. + * + * @see #getCarrierInfoForImsiEncryption * @hide */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @SystemApi public void resetCarrierKeysForImsiEncryption() { try { IPhoneSubInfo info = getSubscriberInfo(); @@ -3954,7 +3980,7 @@ public class TelephonyManager { * @return true if the digit at position keyType is 1, else false. * @hide */ - private static boolean isKeyEnabled(int keyAvailability, int keyType) { + private static boolean isKeyEnabled(int keyAvailability, @KeyType int keyType) { int returnValue = (keyAvailability >> (keyType - 1)) & 1; return (returnValue == 1) ? true : false; } @@ -3963,7 +3989,7 @@ public class TelephonyManager { * If Carrier requires Imsi to be encrypted. * @hide */ - private boolean isImsiEncryptionRequired(int subId, int keyType) { + private boolean isImsiEncryptionRequired(int subId, @KeyType int keyType) { CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager == null) { @@ -9498,16 +9524,28 @@ public class TelephonyManager { return returnValue; } - private int getSubIdForPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) { + /** + * Returns the subscription ID for the given phone account handle. + * + * @param phoneAccountHandle the phone account handle for outgoing calls + * @return subscription ID for the given phone account handle; or + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} + * if not available; or throw a SecurityException if the caller doesn't have the + * permission. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public int getSubIdForPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) { int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID; try { - ITelecomService service = getTelecomService(); + ITelephony service = getITelephony(); if (service != null) { - retval = getSubIdForPhoneAccount(service.getPhoneAccount(phoneAccountHandle)); + retval = service.getSubIdForPhoneAccountHandle( + phoneAccountHandle, mContext.getOpPackageName()); } - } catch (RemoteException e) { + } catch (RemoteException ex) { + Log.e(TAG, "getSubIdForPhoneAccountHandle RemoteException", ex); + ex.rethrowAsRuntimeException(); } - return retval; } @@ -10876,6 +10914,16 @@ public class TelephonyManager { } /** + * Broadcast intent action for Ota emergency number database installation complete. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = + "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED"; + + /** * Returns whether {@link TelephonyManager#ACTION_EMERGENCY_ASSISTANCE emergency assistance} is * available on the device. * <p> diff --git a/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl new file mode 100644 index 000000000000..a648a0e81073 --- /dev/null +++ b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 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. + */ + +/** @hide */ +package android.telephony.cdma; + +parcelable CdmaSmsCbProgramData; + diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index f3a335d93a6c..91aa3ce62cf2 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -574,4 +574,23 @@ interface ISms { * @param destAddress the destination address to test for possible short code */ int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso); + + /** + * Gets the SMSC address from (U)SIM. + * + * @param subId the subscription Id. + * @param callingPackage the package name of the calling app. + * @return the SMSC address string, null if failed. + */ + String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage); + + /** + * Sets the SMSC address on (U)SIM. + * + * @param smsc the SMSC address string. + * @param subId the subscription Id. + * @param callingPackage the package name of the calling app. + * @return true for success, false otherwise. + */ + boolean setSmscAddressOnIccEfForSubscriber(String smsc, int subId, String callingPackage); } diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java index 2096325b09f2..d9d4b6002206 100644 --- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java +++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java @@ -201,4 +201,15 @@ public class ISmsImplBase extends ISms.Stub { int subid, String callingApk, String destAddress, String countryIso) { throw new UnsupportedOperationException(); } + + @Override + public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setSmscAddressOnIccEfForSubscriber( + String smsc, int subId, String callingPackage) { + throw new UnsupportedOperationException(); + } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index ba3ffd461316..316310206f6e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1313,6 +1313,12 @@ interface ITelephony { int getSubIdForPhoneAccount(in PhoneAccount phoneAccount); /** + * Returns the subscription ID associated with the specified PhoneAccountHandle. + */ + int getSubIdForPhoneAccountHandle(in PhoneAccountHandle phoneAccountHandle, + String callingPackage); + + /** * Returns the PhoneAccountHandle associated with a subscription ID. */ PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId); diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index c10169b2d3ee..e3d9c3586256 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -24,8 +24,7 @@ import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; -import org.junit.After; -import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,20 +49,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { phase)); } - @Before - public void setUp() throws Exception { - // Disconnect internet so we can test network health triggered rollbacks - getDevice().executeShellCommand("svc wifi disable"); - getDevice().executeShellCommand("svc data disable"); - } - - @After - public void tearDown() throws Exception { - // Reconnect internet after testing network health triggered rollbacks - getDevice().executeShellCommand("svc wifi enable"); - getDevice().executeShellCommand("svc data enable"); - } - /** * Tests watchdog triggered staged rollbacks involving only apks. */ @@ -121,6 +106,10 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { */ @Test public void testNetworkFailedRollback() throws Exception { + // Disconnect internet so we can test network health triggered rollbacks + getDevice().executeShellCommand("svc wifi disable"); + getDevice().executeShellCommand("svc data disable"); + // Remove available rollbacks and uninstall NetworkStack on /data/ runPhase("testNetworkFailedRollback_Phase1"); // Reduce health check deadline @@ -148,6 +137,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { * Tests passed network health check does not trigger watchdog staged rollbacks. */ @Test + @Ignore("b/143514090") public void testNetworkPassedDoesNotRollback() throws Exception { // Remove available rollbacks and uninstall NetworkStack on /data/ runPhase("testNetworkPassedDoesNotRollback_Phase1"); diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index c0c0361dd92f..ac86778f068f 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -465,9 +465,16 @@ public class ScanResult implements Parcelable { public static final int EID_VHT_OPERATION = 192; @UnsupportedAppUsage public static final int EID_VSA = 221; + public static final int EID_EXTENSION_PRESENT = 255; + + /** + * Extension IDs + */ + public static final int EID_EXT_HE_OPERATION = 36; @UnsupportedAppUsage public int id; + public int idExt; @UnsupportedAppUsage public byte[] bytes; @@ -476,6 +483,7 @@ public class ScanResult implements Parcelable { public InformationElement(InformationElement rhs) { this.id = rhs.id; + this.idExt = rhs.idExt; this.bytes = rhs.bytes.clone(); } } @@ -717,6 +725,7 @@ public class ScanResult implements Parcelable { dest.writeInt(informationElements.length); for (int i = 0; i < informationElements.length; i++) { dest.writeInt(informationElements[i].id); + dest.writeInt(informationElements[i].idExt); dest.writeInt(informationElements[i].bytes.length); dest.writeByteArray(informationElements[i].bytes); } @@ -799,6 +808,7 @@ public class ScanResult implements Parcelable { for (int i = 0; i < n; i++) { sr.informationElements[i] = new InformationElement(); sr.informationElements[i].id = in.readInt(); + sr.informationElements[i].idExt = in.readInt(); int len = in.readInt(); sr.informationElements[i].bytes = new byte[len]; in.readByteArray(sr.informationElements[i].bytes); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 380ebf104a14..07831c71b0d3 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -5240,16 +5240,18 @@ public class WifiManager { /** * Add a listener for Scan Results. See {@link ScanResultsListener}. * Caller will receive the event when scan results are available. - * Caller should use {@link WifiManager#getScanResults()} to get the scan results. + * Caller should use {@link WifiManager#getScanResults()} requires + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results. * Caller can remove a previously registered listener using * {@link WifiManager#removeScanResultsListener(ScanResultsListener)} + * Same caller can add multiple listeners. * <p> * Applications should have the * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers * without the permission will trigger a {@link java.lang.SecurityException}. * <p> * - * @param executor The executor to execute the listener of the {@code listener} object. + * @param executor The executor to execute the listener of the {@code listener} object. * @param listener listener for Scan Results events */ @@ -5267,7 +5269,7 @@ public class WifiManager { iWifiManager.registerScanResultsListener( new Binder(), new ScanResultsListenerProxy(executor, listener), - mContext.getOpPackageName().hashCode()); + listener.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -5289,7 +5291,7 @@ public class WifiManager { if (iWifiManager == null) { throw new RemoteException("Wifi service is not running"); } - iWifiManager.unregisterScanResultsListener(mContext.getOpPackageName().hashCode()); + iWifiManager.unregisterScanResultsListener(listener.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java index 54ec32502878..4973c4cd37fd 100644 --- a/wifi/tests/src/android/net/wifi/ScanResultTest.java +++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.Mockito.validateMockitoUsage; +import android.net.wifi.ScanResult.InformationElement; import android.os.Parcel; import androidx.test.filters.SmallTest; @@ -124,6 +125,25 @@ public class ScanResultTest { } /** + * Verify parcel read/write for ScanResult with Information Element + */ + @Test + public void verifyScanResultParcelWithInformationElement() throws Exception { + ScanResult writeScanResult = createScanResult(); + writeScanResult.informationElements = new ScanResult.InformationElement[2]; + writeScanResult.informationElements[0] = new ScanResult.InformationElement(); + writeScanResult.informationElements[0].id = InformationElement.EID_HT_OPERATION; + writeScanResult.informationElements[0].idExt = 0; + writeScanResult.informationElements[0].bytes = new byte[]{0x11, 0x22, 0x33}; + writeScanResult.informationElements[1] = new ScanResult.InformationElement(); + writeScanResult.informationElements[1].id = InformationElement.EID_EXTENSION_PRESENT; + writeScanResult.informationElements[1].idExt = InformationElement.EID_EXT_HE_OPERATION; + writeScanResult.informationElements[1].bytes = new byte[]{0x44, 0x55, 0x66}; + ScanResult readScanResult = new ScanResult(writeScanResult); + assertScanResultEquals(writeScanResult, readScanResult); + } + + /** * Verify toString for ScanResult. */ @Test @@ -188,5 +208,6 @@ public class ScanResultTest { assertEquals(expected.frequency, actual.frequency); assertEquals(expected.timestamp, actual.timestamp); assertArrayEquals(expected.radioChainInfos, actual.radioChainInfos); + assertArrayEquals(expected.informationElements, actual.informationElements); } } |