diff options
Diffstat (limited to 'core/java')
50 files changed, 451 insertions, 184 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f453ba16043c..750e3d6f6fed 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1537,7 +1537,10 @@ public class Activity extends ContextThemeWrapper } private void dispatchActivityConfigurationChanged() { - getApplication().dispatchActivityConfigurationChanged(this); + // In case the new config comes before mApplication is assigned. + if (getApplication() != null) { + getApplication().dispatchActivityConfigurationChanged(this); + } Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i = 0; i < callbacks.length; i++) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 64a9c441c57f..9e23b5fa692b 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -438,7 +438,7 @@ interface IActivityManager { void requestInteractiveBugReport(); void requestFullBugReport(); - void requestRemoteBugReport(); + void requestRemoteBugReport(long nonce); boolean launchBugReportHandlerApp(); List<String> getBugreportWhitelistedPackages(); diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 2be78033ddf7..cfda7e284c6b 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -293,7 +293,7 @@ interface IActivityTaskManager { * a short predefined amount of time. */ void registerRemoteAnimationForNextActivityStart(in String packageName, - in RemoteAnimationAdapter adapter); + in RemoteAnimationAdapter adapter, in IBinder launchCookie); /** * Registers remote animations for a display. diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING index 23fc6f3bc72a..31c81bef7357 100644 --- a/core/java/android/app/TEST_MAPPING +++ b/core/java/android/app/TEST_MAPPING @@ -115,40 +115,42 @@ "file_patterns": ["(/|^)VoiceInteract[^/]*"] }, { - "name": "CtsContentTestCases", + "name": "CtsOsTestCases", "options": [ { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { "exclude-annotation": "androidx.test.filters.FlakyTest" }, { "exclude-annotation": "org.junit.Ignore" }, { - "include-filter": "android.content.wm.cts" + "include-filter": "android.os.cts.StrictModeTest" } ], "file_patterns": ["(/|^)ContextImpl.java"] }, { - "name": "CtsOsTestCases", + "name": "FrameworksCoreTests", "options": [ { - "include-annotation": "android.platform.test.annotations.Presubmit" - }, - { "exclude-annotation": "androidx.test.filters.FlakyTest" }, { "exclude-annotation": "org.junit.Ignore" }, { - "include-filter": "android.os.cts.StrictModeTest" + "include-filter": "android.content.ContextTest" } ], "file_patterns": ["(/|^)ContextImpl.java"] - }, + } + ], + "presubmit-large": [ { - "name": "FrameworksCoreTests", + "name": "CtsContentTestCases", "options": [ { "exclude-annotation": "androidx.test.filters.FlakyTest" @@ -157,7 +159,7 @@ "exclude-annotation": "org.junit.Ignore" }, { - "include-filter": "android.content.ContextTest" + "include-filter": "android.content.wm.cts" } ], "file_patterns": ["(/|^)ContextImpl.java"] diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 3553748e5004..65793bee353f 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -19,6 +19,7 @@ package android.app.admin; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.Manifest.permission; +import android.accounts.Account; import android.annotation.CallbackExecutor; import android.annotation.ColorInt; import android.annotation.IntDef; @@ -165,6 +166,27 @@ public class DevicePolicyManager { this(context, service, false); } + /** + * Called when a managed profile has been provisioned. + * + * @throws SecurityException if the caller does not hold + * {@link android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + public void finalizeWorkProfileProvisioning( + @NonNull UserHandle managedProfileUser, @Nullable Account migratedAccount) { + Objects.requireNonNull(managedProfileUser, "managedProfileUser can't be null"); + if (mService == null) { + throw new IllegalStateException("Could not find DevicePolicyManagerService"); + } + try { + mService.finalizeWorkProfileProvisioning(managedProfileUser, migratedAccount); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ @VisibleForTesting protected DevicePolicyManager(Context context, IDevicePolicyManager service, @@ -497,6 +519,14 @@ public class DevicePolicyManager { "android.intent.extra.REMOTE_BUGREPORT_HASH"; /** + * Extra for shared bugreport's nonce in long integer type. + * + * @hide + */ + public static final String EXTRA_REMOTE_BUGREPORT_NONCE = + "android.intent.extra.REMOTE_BUGREPORT_NONCE"; + + /** * Extra for remote bugreport notification shown type. * * @hide @@ -3103,11 +3133,19 @@ public class DevicePolicyManager { } } - /** @hide */ - public void resetNewUserDisclaimer() { + /** + * Acknoledges that the new managed user disclaimer was viewed by the (human) user + * so that {@link #ACTION_SHOW_NEW_USER_DISCLAIMER broadcast} is not sent again the next time + * this user is switched to. + * + * @hide + */ + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + public void acknowledgeNewUserDisclaimer() { if (mService != null) { try { - mService.resetNewUserDisclaimer(); + mService.acknowledgeNewUserDisclaimer(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3115,6 +3153,25 @@ public class DevicePolicyManager { } /** + * Checks whether the new managed user disclaimer was viewed by the current user. + * + * @hide + */ + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + @TestApi + public boolean isNewUserDisclaimerAcknowledged() { + if (mService != null) { + try { + return mService.isNewUserDisclaimerAcknowledged(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } + + /** * Return true if the given administrator component is currently active (enabled) in the system. * * @param admin The administrator component to check for. @@ -5673,7 +5730,7 @@ public class DevicePolicyManager { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = - "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER"; + "android.app.action.SHOW_NEW_USER_DISCLAIMER"; /** * Widgets are enabled in keyguard @@ -6361,10 +6418,10 @@ public class DevicePolicyManager { * management app can use {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device * information including manufacturer, model, brand, device and product in the attestation * record. - * Only device owner, profile owner on an organization-owned device and their delegated - * certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and - * {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial number, - * IMEI and MEID correspondingly), if supported by the device + * Only device owner, profile owner on an organization-owned device or affiliated user, and + * their delegated certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} + * and {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial + * number, IMEI and MEID correspondingly), if supported by the device * (see {@link #isDeviceIdAttestationSupported()}). * Additionally, device owner, profile owner on an organization-owned device and their delegated * certificate installers can also request the attestation record to be signed using an diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 7c7478bdb41f..e2e2a353e0c6 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -17,6 +17,7 @@ package android.app.admin; +import android.accounts.Account; import android.app.admin.NetworkEvent; import android.app.IApplicationThread; import android.app.IServiceConnection; @@ -97,6 +98,8 @@ interface IDevicePolicyManager { int getCurrentFailedPasswordAttempts(int userHandle, boolean parent); int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent); + void finalizeWorkProfileProvisioning(in UserHandle managedProfileUser, in Account migratedAccount); + void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, boolean parent); int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle, boolean parent); @@ -264,7 +267,8 @@ interface IDevicePolicyManager { int getLogoutUserId(); void clearLogoutUser(); List<UserHandle> getSecondaryUsers(in ComponentName who); - void resetNewUserDisclaimer(); + void acknowledgeNewUserDisclaimer(); + boolean isNewUserDisclaimerAcknowledged(); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); diff --git a/core/java/android/content/TEST_MAPPING b/core/java/android/content/TEST_MAPPING index 614143e7c04d..7f1d0d1d05cf 100644 --- a/core/java/android/content/TEST_MAPPING +++ b/core/java/android/content/TEST_MAPPING @@ -1,21 +1,6 @@ { "presubmit": [ { - "name": "CtsContentTestCases", - "options": [ - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation": "org.junit.Ignore" - }, - { - "include-filter": "android.content.wm.cts" - } - ], - "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java"] - }, - { "name": "CtsOsTestCases", "options": [ { @@ -51,5 +36,22 @@ ], "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java", "(/|^)ComponentCallbacksController.java"] } + ], + "presubmit-large": [ + { + "name": "CtsContentTestCases", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + }, + { + "include-filter": "android.content.wm.cts" + } + ], + "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java"] + } ] }
\ No newline at end of file diff --git a/core/java/android/content/om/TEST_MAPPING b/core/java/android/content/om/TEST_MAPPING index d8f885439b34..6185cf64ad12 100644 --- a/core/java/android/content/om/TEST_MAPPING +++ b/core/java/android/content/om/TEST_MAPPING @@ -21,7 +21,9 @@ "include-filter": "android.appsecurity.cts.OverlayHostTest" } ] - }, + } + ], + "presubmit-large": [ { "name": "CtsContentTestCases", "options": [ diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl index f72288c670d9..9a7a949e3cd2 100644 --- a/core/java/android/content/pm/IPackageInstallerSession.aidl +++ b/core/java/android/content/pm/IPackageInstallerSession.aidl @@ -55,4 +55,5 @@ interface IPackageInstallerSession { int getParentSessionId(); boolean isStaged(); + int getInstallFlags(); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 3f8aedb31ea9..4030708d6a53 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1432,6 +1432,18 @@ public class PackageInstaller { } /** + * @return Session's {@link SessionParams#installFlags}. + * @hide + */ + public int getInstallFlags() { + try { + return mSession.getInstallFlags(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * @return the session ID of the multi-package session that this belongs to or * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session. */ diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING index 8bc3734e060d..0a69413b36ea 100644 --- a/core/java/android/content/pm/TEST_MAPPING +++ b/core/java/android/content/pm/TEST_MAPPING @@ -19,6 +19,16 @@ "name": "CarrierAppIntegrationTestCases" }, { + "name": "CtsIncrementalInstallHostTestCases", + "options": [ + { + "include-filter": "android.incrementalinstall.cts.IncrementalFeatureTest" + } + ] + } + ], + "presubmit-large": [ + { "name": "CtsContentTestCases", "options": [ { @@ -31,14 +41,6 @@ "include-filter": "android.content.pm.cts" } ] - }, - { - "name": "CtsIncrementalInstallHostTestCases", - "options": [ - { - "include-filter": "android.incrementalinstall.cts.IncrementalFeatureTest" - } - ] } ], "postsubmit": [ diff --git a/core/java/android/content/res/TEST_MAPPING b/core/java/android/content/res/TEST_MAPPING index c02af59ab72e..535afd361f01 100644 --- a/core/java/android/content/res/TEST_MAPPING +++ b/core/java/android/content/res/TEST_MAPPING @@ -2,7 +2,9 @@ "presubmit": [ { "name": "CtsResourcesLoaderTests" - }, + } + ], + "presubmit-large": [ { "name": "CtsContentTestCases", "options": [ diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 56f81423db4e..b97055976e3e 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -306,22 +306,21 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan throw new IllegalArgumentException("Must supply an enrollment callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "enrollment already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnEnrollCancelListener()); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "enrollment already canceled"); + return; } if (mService != null) { try { mEnrollmentCallback = callback; Trace.beginSection("FaceManager#enroll"); - mService.enroll(userId, mToken, hardwareAuthToken, mServiceReceiver, - mContext.getOpPackageName(), disabledFeatures, previewSurface, - debugConsent); + final long enrollId = mService.enroll(userId, mToken, hardwareAuthToken, + mServiceReceiver, mContext.getOpPackageName(), disabledFeatures, + previewSurface, debugConsent); + if (cancel != null) { + cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception in enroll: ", e); // Though this may not be a hardware issue, it will cause apps to give up or @@ -359,21 +358,20 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan throw new IllegalArgumentException("Must supply an enrollment callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "enrollRemotely is already canceled."); - return; - } else { - cancel.setOnCancelListener(new OnEnrollCancelListener()); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "enrollRemotely is already canceled."); + return; } if (mService != null) { try { mEnrollmentCallback = callback; Trace.beginSection("FaceManager#enrollRemotely"); - mService.enrollRemotely(userId, mToken, hardwareAuthToken, mServiceReceiver, - mContext.getOpPackageName(), disabledFeatures); + final long enrolId = mService.enrollRemotely(userId, mToken, hardwareAuthToken, + mServiceReceiver, mContext.getOpPackageName(), disabledFeatures); + if (cancel != null) { + cancel.setOnCancelListener(new OnEnrollCancelListener(enrolId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception in enrollRemotely: ", e); // Though this may not be a hardware issue, it will cause apps to give up or @@ -713,10 +711,10 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } } - private void cancelEnrollment() { + private void cancelEnrollment(long requestId) { if (mService != null) { try { - mService.cancelEnrollment(mToken); + mService.cancelEnrollment(mToken, requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1100,9 +1098,16 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } private class OnEnrollCancelListener implements OnCancelListener { + private final long mAuthRequestId; + + private OnEnrollCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelEnrollment(); + Slog.d(TAG, "Cancel face enrollment requested for: " + mAuthRequestId); + cancelEnrollment(mAuthRequestId); } } diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index e9198246dee3..989b001ca8bf 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -76,15 +76,16 @@ interface IFaceService { void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId); // Start face enrollment - void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, - String opPackageName, in int [] disabledFeatures, in Surface previewSurface, boolean debugConsent); + long enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, + String opPackageName, in int [] disabledFeatures, + in Surface previewSurface, boolean debugConsent); // Start remote face enrollment - void enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, + long enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, String opPackageName, in int [] disabledFeatures); // Cancel enrollment in progress - void cancelEnrollment(IBinder token); + void cancelEnrollment(IBinder token, long requestId); // Removes the specified face enrollment for the specified userId. void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver, diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index fe04e5d35784..acf9427b1241 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -183,9 +183,16 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } private class OnEnrollCancelListener implements OnCancelListener { + private final long mAuthRequestId; + + private OnEnrollCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelEnrollment(); + Slog.d(TAG, "Cancel fingerprint enrollment requested for: " + mAuthRequestId); + cancelEnrollment(mAuthRequestId); } } @@ -646,20 +653,19 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing throw new IllegalArgumentException("Must supply an enrollment callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "enrollment already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnEnrollCancelListener()); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "enrollment already canceled"); + return; } if (mService != null) { try { mEnrollmentCallback = callback; - mService.enroll(mToken, hardwareAuthToken, userId, mServiceReceiver, - mContext.getOpPackageName(), enrollReason); + final long enrollId = mService.enroll(mToken, hardwareAuthToken, userId, + mServiceReceiver, mContext.getOpPackageName(), enrollReason); + if (cancel != null) { + cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception in enroll: ", e); // Though this may not be a hardware issue, it will cause apps to give up or try @@ -1302,9 +1308,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing return allSensors.isEmpty() ? null : allSensors.get(0); } - private void cancelEnrollment() { + private void cancelEnrollment(long requestId) { if (mService != null) try { - mService.cancelEnrollment(mToken); + mService.cancelEnrollment(mToken, requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index ba1dc6da62a6..cbff8b11a72a 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -84,11 +84,11 @@ interface IFingerprintService { void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId); // Start fingerprint enrollment - void enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver, + long enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver, String opPackageName, int enrollReason); // Cancel enrollment in progress - void cancelEnrollment(IBinder token); + void cancelEnrollment(IBinder token, long requestId); // Any errors resulting from this call will be returned to the listener void remove(IBinder token, int fingerId, int userId, IFingerprintServiceReceiver receiver, diff --git a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java index df13ade2bf5e..bd25b8f2ad88 100644 --- a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java +++ b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java @@ -16,9 +16,9 @@ package android.hardware.location; +import android.os.BadParcelableException; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; /** * Geofence Hardware Request used for internal location services communication. @@ -139,11 +139,8 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable { @Override public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) { int geofenceType = parcel.readInt(); - if(geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) { - Log.e( - "GeofenceHardwareRequest", - String.format("Invalid Geofence type: %d", geofenceType)); - return null; + if (geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) { + throw new BadParcelableException("Invalid Geofence type: " + geofenceType); } GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence( diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 539fd4adb0a0..e1ccc4fb740b 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -45,4 +45,7 @@ interface INfcTag boolean canMakeReadOnly(int ndefType); int getMaxTransceiveLength(int technology); boolean getExtendedLengthApdusSupported(); + + void setTagUpToDate(long cookie); + boolean isTagUpToDate(long cookie); } diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java index 398ec63a931b..731d1ba78299 100644 --- a/core/java/android/nfc/Tag.java +++ b/core/java/android/nfc/Tag.java @@ -34,6 +34,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; +import android.os.SystemClock; import java.io.IOException; import java.util.Arrays; @@ -121,6 +122,7 @@ public final class Tag implements Parcelable { final INfcTag mTagService; // interface to NFC service, will be null if mock tag int mConnectedTechnology; + long mCookie; /** * Hidden constructor to be used by NFC service and internal classes. @@ -140,6 +142,17 @@ public final class Tag implements Parcelable { mTagService = tagService; mConnectedTechnology = -1; + mCookie = SystemClock.elapsedRealtime(); + + if (tagService == null) { + return; + } + + try { + tagService.setTagUpToDate(mCookie); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } } /** @@ -361,6 +374,22 @@ public final class Tag implements Parcelable { /** @hide */ @UnsupportedAppUsage public INfcTag getTagService() { + if (mTagService == null) { + return null; + } + + try { + if (!mTagService.isTagUpToDate(mCookie)) { + String id_str = ""; + for (int i = 0; i < mId.length; i++) { + id_str = id_str + String.format("%02X ", mId[i]); + } + String msg = "Permission Denial: Tag ( ID: " + id_str + ") is out of date"; + throw new SecurityException(msg); + } + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } return mTagService; } diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index e06e7b6be90a..d0a77a031c99 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -474,6 +474,7 @@ public final class Parcel { */ public final void recycle() { if (DEBUG_RECYCLE) mStack = null; + mClassCookies = null; freeBuffer(); if (mOwnsNativeParcelObject) { diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index e58419fb688d..338ad242874f 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -513,6 +513,13 @@ public final class DeviceConfig { public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot"; /** + * Definitions for voice interaction related functions. + * + * @hide + */ + public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction"; + + /** * List of namespaces which can be read without READ_DEVICE_CONFIG permission * * @hide diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 042445b5011f..9b51ab9e30a7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9675,6 +9675,13 @@ public final class Settings { "lockscreen_use_double_line_clock"; /** + * Whether to show the vibrate icon in the Status Bar (default off) + * + * @hide + */ + public static final String STATUS_BAR_SHOW_VIBRATE_ICON = "status_bar_show_vibrate_icon"; + + /** * Specifies whether the web action API is enabled. * * @hide @@ -13769,6 +13776,16 @@ public final class Settings { public static final String EMERGENCY_AFFORDANCE_NEEDED = "emergency_affordance_needed"; /** + * The power button "cooldown" period in milliseconds after the Emergency gesture is + * triggered, during which single-key actions on the power button are suppressed. Cooldown + * period is disabled if set to zero. + * + * @hide + */ + public static final String EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS = + "emergency_gesture_power_button_cooldown_period_ms"; + + /** * Whether to enable automatic system server heap dumps. This only works on userdebug or * eng builds, not on user builds. This is set by the user and overrides the config value. * 1 means enable, 0 means disable. diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java index 7ed733cb4f4c..9d648a6995fb 100644 --- a/core/java/android/service/gatekeeper/GateKeeperResponse.java +++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java @@ -105,7 +105,7 @@ public final class GateKeeperResponse implements Parcelable { dest.writeInt(mTimeout); } else if (mResponseCode == RESPONSE_OK) { dest.writeInt(mShouldReEnroll ? 1 : 0); - if (mPayload != null) { + if (mPayload != null && mPayload.length > 0) { dest.writeInt(mPayload.length); dest.writeByteArray(mPayload); } else { diff --git a/core/java/android/service/voice/AbstractHotwordDetector.java b/core/java/android/service/voice/AbstractHotwordDetector.java index dbe108974684..192260791a8b 100644 --- a/core/java/android/service/voice/AbstractHotwordDetector.java +++ b/core/java/android/service/voice/AbstractHotwordDetector.java @@ -44,14 +44,17 @@ abstract class AbstractHotwordDetector implements HotwordDetector { private final IVoiceInteractionManagerService mManagerService; private final Handler mHandler; private final HotwordDetector.Callback mCallback; + private final int mDetectorType; AbstractHotwordDetector( IVoiceInteractionManagerService managerService, - HotwordDetector.Callback callback) { + HotwordDetector.Callback callback, + int detectorType) { mManagerService = managerService; // TODO: this needs to be supplied from above mHandler = new Handler(Looper.getMainLooper()); mCallback = callback; + mDetectorType = detectorType; } /** @@ -104,19 +107,20 @@ abstract class AbstractHotwordDetector implements HotwordDetector { Slog.d(TAG, "updateState()"); } synchronized (mLock) { - updateStateLocked(options, sharedMemory, null /* callback */); + updateStateLocked(options, sharedMemory, null /* callback */, mDetectorType); } } protected void updateStateLocked(@Nullable PersistableBundle options, - @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) { + @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback, + int detectorType) { if (DEBUG) { Slog.d(TAG, "updateStateLocked()"); } Identity identity = new Identity(); identity.packageName = ActivityThread.currentOpPackageName(); try { - mManagerService.updateState(identity, options, sharedMemory, callback); + mManagerService.updateState(identity, options, sharedMemory, callback, detectorType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index face870ca1b4..c9daf52b5685 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -578,7 +578,9 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { IVoiceInteractionManagerService modelManagementService, int targetSdkVersion, boolean supportHotwordDetectionService, @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) { - super(modelManagementService, callback); + super(modelManagementService, callback, + supportHotwordDetectionService ? DETECTOR_TYPE_TRUSTED_HOTWORD_DSP + : DETECTOR_TYPE_NORMAL); mHandler = new MyHandler(); mText = text; @@ -590,7 +592,8 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { mTargetSdkVersion = targetSdkVersion; mSupportHotwordDetectionService = supportHotwordDetectionService; if (mSupportHotwordDetectionService) { - updateStateLocked(options, sharedMemory, mInternalCallback); + updateStateLocked(options, sharedMemory, mInternalCallback, + DETECTOR_TYPE_TRUSTED_HOTWORD_DSP); } try { Identity identity = new Identity(); diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java index e2478195bdde..969ec22beb97 100644 --- a/core/java/android/service/voice/HotwordDetector.java +++ b/core/java/android/service/voice/HotwordDetector.java @@ -37,6 +37,27 @@ import android.os.SharedMemory; public interface HotwordDetector { /** + * Indicates that it is a non-trusted hotword detector. + * + * @hide + */ + int DETECTOR_TYPE_NORMAL = 0; + + /** + * Indicates that it is a DSP trusted hotword detector. + * + * @hide + */ + int DETECTOR_TYPE_TRUSTED_HOTWORD_DSP = 1; + + /** + * Indicates that it is a software trusted hotword detector. + * + * @hide + */ + int DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE = 2; + + /** * Starts hotword recognition. * <p> * On calling this, the system streams audio from the device microphone to this application's @@ -98,6 +119,22 @@ public interface HotwordDetector { void updateState(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory); /** + * @hide + */ + static String detectorTypeToString(int detectorType) { + switch (detectorType) { + case DETECTOR_TYPE_NORMAL: + return "normal"; + case DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return "trusted_hotword_dsp"; + case DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return "trusted_hotword_software"; + default: + return Integer.toString(detectorType); + } + } + + /** * The callback to notify of detection events. */ interface Callback { diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java index f7a3415259fd..512a654adbab 100644 --- a/core/java/android/service/voice/SoftwareHotwordDetector.java +++ b/core/java/android/service/voice/SoftwareHotwordDetector.java @@ -60,14 +60,15 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { PersistableBundle options, SharedMemory sharedMemory, HotwordDetector.Callback callback) { - super(managerService, callback); + super(managerService, callback, DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE); mManagerService = managerService; mAudioFormat = audioFormat; mCallback = callback; mHandler = new Handler(Looper.getMainLooper()); updateStateLocked(options, sharedMemory, - new InitializationStateListener(mHandler, mCallback)); + new InitializationStateListener(mHandler, mCallback), + DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE); } @RequiresPermission(RECORD_AUDIO) diff --git a/core/java/android/util/TimingsTraceLog.java b/core/java/android/util/TimingsTraceLog.java index 5370645d31bc..f3353f45d434 100644 --- a/core/java/android/util/TimingsTraceLog.java +++ b/core/java/android/util/TimingsTraceLog.java @@ -127,7 +127,7 @@ public class TimingsTraceLog { * Logs a duration so it can be parsed by external tools for performance reporting. */ public void logDuration(String name, long timeMs) { - Slog.d(mTag, name + " took to complete: " + timeMs + "ms"); + Slog.v(mTag, name + " took to complete: " + timeMs + "ms"); } /** diff --git a/core/java/android/util/apk/TEST_MAPPING b/core/java/android/util/apk/TEST_MAPPING index 4598b4ffe4f6..e1825210bfd9 100644 --- a/core/java/android/util/apk/TEST_MAPPING +++ b/core/java/android/util/apk/TEST_MAPPING @@ -1,21 +1,23 @@ { "presubmit": [ { - "name": "CtsContentTestCases", + "name": "FrameworksCoreTests", "options": [ { - "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest" - }, - { - "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest" + "include-filter": "android.util.apk.SourceStampVerifierTest" } ] - }, + } + ], + "presubmit-large": [ { - "name": "FrameworksCoreTests", + "name": "CtsContentTestCases", "options": [ { - "include-filter": "android.util.apk.SourceStampVerifierTest" + "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest" + }, + { + "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest" } ] } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 9da50889e43f..46ee0f839fa9 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -306,7 +306,7 @@ interface IWindowSession { */ void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window, in IBinder hostInputToken, int flags, int privateFlags, int type, - out InputChannel outInputChannel); + in IBinder focusGrantToken, out InputChannel outInputChannel); /** * Update the flags on an input channel associated with a particular surface. diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 960d23d7afb0..a686cbf257ef 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -245,6 +245,7 @@ public final class SurfaceControl implements Parcelable { @SurfaceControl.BufferTransform int transformHint); private static native int nativeGetTransformHint(long nativeObject); private static native int nativeGetLayerId(long nativeObject); + private static native void nativeSanitize(long transactionObject); /** * Transforms that can be applied to buffers as they are displayed to a window. @@ -3544,6 +3545,13 @@ public final class SurfaceControl implements Parcelable { } /** + * @hide + */ + public void sanitize() { + nativeSanitize(mNativeObject); + } + + /** * Merge the other transaction into this transaction, clearing the * other transaction as if it had been applied. * diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java index a6c5042db275..a312939e6522 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -231,7 +231,7 @@ public class SurfaceControlViewHost { public @Nullable SurfacePackage getSurfacePackage() { if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) { return new SurfacePackage(mSurfaceControl, mAccessibilityEmbeddedConnection, - mViewRoot.getInputToken()); + mWm.getFocusGrantToken()); } else { return null; } diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java index efffa2b05a1e..aba79d5b87c3 100644 --- a/core/java/android/view/ViewRootInsetsControllerHost.java +++ b/core/java/android/view/ViewRootInsetsControllerHost.java @@ -171,8 +171,9 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host { public void setSystemBarsAppearance(int appearance, int mask) { mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED; final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags; - if (insetsFlags.appearance != appearance) { - insetsFlags.appearance = (insetsFlags.appearance & ~mask) | (appearance & mask); + final int newAppearance = (insetsFlags.appearance & ~mask) | (appearance & mask); + if (insetsFlags.appearance != newAppearance) { + insetsFlags.appearance = newAppearance; mViewRoot.mWindowAttributesChanged = true; mViewRoot.scheduleTraversals(); } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index ffb7efa67243..d5cf1a360b0f 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -22,6 +22,7 @@ import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; +import android.os.Binder; import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; @@ -75,6 +76,7 @@ public class WindowlessWindowManager implements IWindowSession { private final Configuration mConfiguration; private final IWindowSession mRealWm; private final IBinder mHostInputToken; + private final IBinder mFocusGrantToken = new Binder(); private int mForceHeight = -1; private int mForceWidth = -1; @@ -91,6 +93,10 @@ public class WindowlessWindowManager implements IWindowSession { mConfiguration.setTo(configuration); } + IBinder getFocusGrantToken() { + return mFocusGrantToken; + } + /** * Utility API. */ @@ -153,10 +159,10 @@ public class WindowlessWindowManager implements IWindowSession { mRealWm.grantInputChannel(displayId, new SurfaceControl(sc, "WindowlessWindowManager.addToDisplay"), window, mHostInputToken, attrs.flags, attrs.privateFlags, attrs.type, - outInputChannel); + mFocusGrantToken, outInputChannel); } else { mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags, - attrs.privateFlags, attrs.type, outInputChannel); + attrs.privateFlags, attrs.type, mFocusGrantToken, outInputChannel); } } catch (RemoteException e) { Log.e(TAG, "Failed to grant input to surface: ", e); @@ -464,7 +470,7 @@ public class WindowlessWindowManager implements IWindowSession { @Override public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window, - IBinder hostInputToken, int flags, int privateFlags, int type, + IBinder hostInputToken, int flags, int privateFlags, int type, IBinder focusGrantToken, InputChannel outInputChannel) { } diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index cc47f09d4e8d..a4db84055142 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -290,6 +290,8 @@ public abstract class ContentCaptureSession implements AutoCloseable { * <p>Typically used to change the context associated with the default session from an activity. */ public final void setContentCaptureContext(@Nullable ContentCaptureContext context) { + if (!isContentCaptureEnabled()) return; + mClientContext = context; updateContentCaptureContext(context); } diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java index 3012e9344a1b..b57134b3ec44 100644 --- a/core/java/android/view/translation/UiTranslationManager.java +++ b/core/java/android/view/translation/UiTranslationManager.java @@ -101,26 +101,26 @@ public final class UiTranslationManager { public static final String LOG_TAG = "UiTranslation"; /** - * The state caller request to disable utranslation,, it is no longer need to ui translation. + * The state the caller requests to enable UI translation. * * @hide */ public static final int STATE_UI_TRANSLATION_STARTED = 0; /** - * The state caller request to pause ui translation, it will switch back to the original text. + * The state caller requests to pause UI translation. It will switch back to the original text. * * @hide */ public static final int STATE_UI_TRANSLATION_PAUSED = 1; /** - * The state caller request to resume the paused ui translation, it will show the translated + * The state caller requests to resume the paused UI translation. It will show the translated * text again if the text had been translated. * * @hide */ public static final int STATE_UI_TRANSLATION_RESUMED = 2; /** - * The state the caller request to enable ui translation. + * The state the caller requests to disable UI translation when it no longer needs translation. * * @hide */ diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 2d1f17a420fa..a0ec48bc6beb 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -297,12 +297,12 @@ public final class SelectionActionModeHelper { } else { mTextClassification = null; } - final SelectionModifierCursorController controller = mEditor.getSelectionController(); - if (controller != null - && (mTextView.isTextSelectable() || mTextView.isTextEditable())) { - controller.show(); - } if (mEditor.startActionModeInternal(actionMode)) { + final SelectionModifierCursorController controller = mEditor.getSelectionController(); + if (controller != null + && (mTextView.isTextSelectable() || mTextView.isTextEditable())) { + controller.show(); + } if (result != null) { switch (actionMode) { case Editor.TextActionMode.SELECTION: diff --git a/core/java/android/widget/TextViewTranslationCallback.java b/core/java/android/widget/TextViewTranslationCallback.java index 942be21b1ade..1713d842560b 100644 --- a/core/java/android/widget/TextViewTranslationCallback.java +++ b/core/java/android/widget/TextViewTranslationCallback.java @@ -89,7 +89,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { originalTranslationMethod); } final TransformationMethod transformation = mTranslationTransformation; - runWithAnimation( + runChangeTextWithAnimationIfNeeded( (TextView) view, () -> { mIsShowingTranslation = true; @@ -122,7 +122,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { if (mTranslationTransformation != null) { final TransformationMethod transformation = mTranslationTransformation.getOriginalTransformationMethod(); - runWithAnimation( + runChangeTextWithAnimationIfNeeded( (TextView) view, () -> { mIsShowingTranslation = false; @@ -232,10 +232,16 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { * Applies a simple text alpha animation when toggling between original and translated text. The * text is fully faded out, then swapped to the new text, then the fading is reversed. * - * @param runnable the operation to run on the view after the text is faded out, to change to - * displaying the original or translated text. + * @param changeTextRunnable the operation to run on the view after the text is faded out, to + * change to displaying the original or translated text. */ - private void runWithAnimation(TextView view, Runnable runnable) { + private void runChangeTextWithAnimationIfNeeded(TextView view, Runnable changeTextRunnable) { + boolean areAnimatorsEnabled = ValueAnimator.areAnimatorsEnabled(); + if (!areAnimatorsEnabled) { + // The animation is disabled, just change display text + changeTextRunnable.run(); + return; + } if (mAnimator != null) { mAnimator.end(); // Note: mAnimator is now null; do not use again here. @@ -269,7 +275,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { @Override public void onAnimationRepeat(Animator animation) { - runnable.run(); + changeTextRunnable.run(); } }); mAnimator.start(); diff --git a/core/java/android/window/SplashScreen.java b/core/java/android/window/SplashScreen.java index 090dbff488e9..251e0acb97e6 100644 --- a/core/java/android/window/SplashScreen.java +++ b/core/java/android/window/SplashScreen.java @@ -99,8 +99,12 @@ public interface SplashScreen { * <p> * To reset to the default theme, set this the themeId to {@link Resources#ID_NULL}. * <p> - * <b>Note:</b> The theme name must be stable across versions, otherwise it won't be found - * after your application is updated. + * <b>Note:</b> Internally, the theme name is resolved and persisted. This means that the theme + * name must be stable across versions, otherwise it won't be found after your application is + * updated. + * + * @param themeId The ID of the splashscreen theme to be used in place of the one defined in + * the manifest. */ void setSplashScreenTheme(@StyleRes int themeId); diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 998526209c72..61c9128e499e 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -242,12 +242,14 @@ interface IVoiceInteractionManagerService { * {@link HotwordDetectionService}. Use this to provide the hotword models data or other * such data to the trusted process. * @param callback Use this to report {@link HotwordDetectionService} status. + * @param detectorType Indicate which detector is used. */ void updateState( in Identity originatorIdentity, in PersistableBundle options, in SharedMemory sharedMemory, - in IHotwordRecognitionStatusCallback callback); + in IHotwordRecognitionStatusCallback callback, + int detectorType); /** * Requests to shutdown hotword detection service. diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java index 9ced6097804d..c379385429b5 100644 --- a/core/java/com/android/internal/infra/ServiceConnector.java +++ b/core/java/com/android/internal/infra/ServiceConnector.java @@ -507,10 +507,21 @@ public interface ServiceConnector<I extends IInterface> { void unbindJobThread() { cancelTimeout(); I service = mService; + // TODO(b/224695239): This is actually checking wasConnected. Rename and/or fix + // implementation based on what this should actually be checking. At least the first + // check for calling unbind is the correct behavior, though. boolean wasBound = service != null; + if (wasBound || mBinding) { + try { + mContext.unbindService(mServiceConnection); + } catch (IllegalArgumentException e) { // TODO(b/224697137): Fix the race condition + // that requires catching this (crashes if + // service isn't currently bound). + Log.e(LOG_TAG, "Failed to unbind: " + e); + } + } if (wasBound) { onServiceConnectionStatusChanged(service, false); - mContext.unbindService(mServiceConnection); service.asBinder().unlinkToDeath(this, 0); mService = null; } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 169eff009bff..988ddb28af62 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -4664,7 +4664,6 @@ public class BatteryStatsImpl extends BatteryStats { public void noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { - uid = mapUid(uid); noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } @@ -4696,15 +4695,21 @@ public class BatteryStatsImpl extends BatteryStats { private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { + final int mappedUid = mapUid(uid); if (historyName == null) { historyName = name; } - if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid, - 0)) { + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, + mappedUid, 0)) { return; } addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START, - historyName, uid); + historyName, mappedUid); + if (mappedUid != uid) { + // Prevent the isolated uid mapping from being removed while the wakelock is + // being held. + incrementIsolatedUidRefCount(uid); + } } public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { @@ -4714,7 +4719,6 @@ public class BatteryStatsImpl extends BatteryStats { public void noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { - uid = mapUid(uid); noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } @@ -4746,15 +4750,20 @@ public class BatteryStatsImpl extends BatteryStats { private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { + final int mappedUid = mapUid(uid); if (historyName == null) { historyName = name; } - if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid, - 0)) { + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, + mappedUid, 0)) { return; } addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, - historyName, uid); + historyName, mappedUid); + if (mappedUid != uid) { + // Decrement the ref count for the isolated uid and delete the mapping if uneeded. + maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs); + } } void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) { diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java index eb5993dc2d61..31b807201bb6 100644 --- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java +++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java @@ -99,9 +99,9 @@ public class MobileRadioPowerCalculator extends PowerCalculator { calculateApp(app, uid, powerPerPacketMah, total, query); } - final long consumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC(); - final int powerModel = getPowerModel(consumptionUC, query); - calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC); + final long totalConsumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC(); + final int powerModel = getPowerModel(totalConsumptionUC, query); + calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, totalConsumptionUC); if (total.remainingPowerMah != 0 || total.totalAppPowerMah != 0) { builder.getAggregateBatteryConsumerBuilder( @@ -229,12 +229,13 @@ public class MobileRadioPowerCalculator extends PowerCalculator { private void calculateRemaining(PowerAndDuration total, @BatteryConsumer.PowerModel int powerModel, BatteryStats batteryStats, - long rawRealtimeUs, long consumptionUC) { + long rawRealtimeUs, long totalConsumptionUC) { long signalTimeMs = 0; double powerMah = 0; if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) { - powerMah = uCtoMah(consumptionUC); + powerMah = uCtoMah(totalConsumptionUC) - total.totalAppPowerMah; + if (powerMah < 0) powerMah = 0; } for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) { diff --git a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl index 419b1f8feac7..d69a240b140b 100644 --- a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl +++ b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl @@ -16,7 +16,7 @@ package com.android.internal.policy; interface IKeyguardStateCallback { - void onShowingStateChanged(boolean showing); + void onShowingStateChanged(boolean showing, int userId); void onSimSecureStateChanged(boolean simSecure); void onInputRestrictedStateChanged(boolean inputRestricted); void onTrustedChanged(boolean trusted); diff --git a/core/java/com/android/internal/policy/SystemBarUtils.java b/core/java/com/android/internal/policy/SystemBarUtils.java index 6bf1333097f7..5358b96a0f97 100644 --- a/core/java/com/android/internal/policy/SystemBarUtils.java +++ b/core/java/com/android/internal/policy/SystemBarUtils.java @@ -43,7 +43,7 @@ public final class SystemBarUtils { * Gets the status bar height with a specific display cutout. */ public static int getStatusBarHeight(Resources res, DisplayCutout cutout) { - final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height); + final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height_default); final int safeInsetTop = cutout == null ? 0 : cutout.getSafeInsetTop(); final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top; // The status bar height should be: diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index e6deada45fc1..a7d78eb02ed1 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -66,7 +66,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -76,8 +75,6 @@ import java.util.function.Consumer; public class ConversationLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -150,6 +147,7 @@ public class ConversationLayout extends FrameLayout private Icon mShortcutIcon; private View mAppNameDivider; private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this); + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public ConversationLayout(@NonNull Context context) { super(context); @@ -462,8 +460,12 @@ public class ConversationLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -472,6 +474,12 @@ public class ConversationLayout extends FrameLayout updateTitleAndNamesDisplay(); updateConversationLayout(); + + // Recycle everything at the end of the update, now that we know it's no longer needed. + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); + } + mToRecycle.clear(); } /** @@ -745,18 +753,18 @@ public class ConversationLayout extends FrameLayout MessagingGroup group = oldGroups.get(i); if (!mGroups.contains(group)) { List<MessagingMessage> messages = group.getMessages(); - Runnable endRunnable = () -> { - mMessagingLinearLayout.removeTransientView(group); - group.recycle(); - }; - boolean wasShown = group.isShown(); mMessagingLinearLayout.removeView(group); if (wasShown && !MessagingLinearLayout.isGone(group)) { mMessagingLinearLayout.addTransientView(group, 0); - group.removeGroupAnimated(endRunnable); + group.removeGroupAnimated(() -> { + mMessagingLinearLayout.removeTransientView(group); + group.recycle(); + }); } else { - endRunnable.run(); + // Defer recycling until after the update is done, since we may still need the + // old group around to perform other updates. + mToRecycle.add(group); } mMessages.removeAll(messages); mHistoricMessages.removeAll(messages); diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index f30b8442dc35..eaa9bcd72b84 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -263,7 +263,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return createdGroup; } - public void removeMessage(MessagingMessage messagingMessage) { + public void removeMessage(MessagingMessage messagingMessage, + ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { View view = messagingMessage.getView(); boolean wasShown = view.isShown(); ViewGroup messageParent = (ViewGroup) view.getParent(); @@ -271,15 +272,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return; } messageParent.removeView(view); - Runnable recycleRunnable = () -> { - messageParent.removeTransientView(view); - messagingMessage.recycle(); - }; if (wasShown && !MessagingLinearLayout.isGone(view)) { messageParent.addTransientView(view, 0); - performRemoveAnimation(view, recycleRunnable); + performRemoveAnimation(view, () -> { + messageParent.removeTransientView(view); + messagingMessage.recycle(); + }); } else { - recycleRunnable.run(); + toRecycle.add(messagingMessage); } } diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index e1602a981920..914de9e5e643 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -51,7 +51,6 @@ import com.android.internal.util.ContrastColorUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -62,8 +61,6 @@ public class MessagingLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { private static final float COLOR_SHIFT_AMOUNT = 60; - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -89,6 +86,7 @@ public class MessagingLayout extends FrameLayout private boolean mIsCollapsed; private ImageResolver mImageResolver; private CharSequence mConversationTitle; + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public MessagingLayout(@NonNull Context context) { super(context); @@ -212,8 +210,12 @@ public class MessagingLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -223,6 +225,12 @@ public class MessagingLayout extends FrameLayout // after groups are finalized, hide the first sender name if it's showing as the title mPeopleHelper.maybeHideFirstSenderName(mGroups, mIsOneToOne, mConversationTitle); updateImageMessages(); + + // Recycle everything at the end of the update, now that we know it's no longer needed. + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); + } + mToRecycle.clear(); } private void updateImageMessages() { @@ -263,18 +271,17 @@ public class MessagingLayout extends FrameLayout MessagingGroup group = oldGroups.get(i); if (!mGroups.contains(group)) { List<MessagingMessage> messages = group.getMessages(); - Runnable endRunnable = () -> { - mMessagingLinearLayout.removeTransientView(group); - group.recycle(); - }; boolean wasShown = group.isShown(); mMessagingLinearLayout.removeView(group); if (wasShown && !MessagingLinearLayout.isGone(group)) { mMessagingLinearLayout.addTransientView(group, 0); - group.removeGroupAnimated(endRunnable); + group.removeGroupAnimated(() -> { + mMessagingLinearLayout.removeTransientView(group); + group.recycle(); + }); } else { - endRunnable.run(); + mToRecycle.add(group); } mMessages.removeAll(messages); mHistoricMessages.removeAll(messages); diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java index cb1d387dbd07..c06f5f75514f 100644 --- a/core/java/com/android/internal/widget/MessagingLinearLayout.java +++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java @@ -365,6 +365,7 @@ public class MessagingLinearLayout extends ViewGroup { default int getExtraSpacing() { return 0; } + void recycle(); } public static class LayoutParams extends MarginLayoutParams { diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java index 8c8437951402..2cc0d2305a78 100644 --- a/core/java/com/android/internal/widget/MessagingMessage.java +++ b/core/java/com/android/internal/widget/MessagingMessage.java @@ -20,6 +20,7 @@ import android.app.ActivityManager; import android.app.Notification; import android.view.View; +import java.util.ArrayList; import java.util.Objects; /** @@ -96,8 +97,8 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { return sameAs(message.getMessage()); } - default void removeMessage() { - getGroup().removeMessage(this); + default void removeMessage(ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { + getGroup().removeMessage(this, toRecycle); } default void setMessagingGroup(MessagingGroup group) { |