summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java13
-rw-r--r--apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java17
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java8
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java128
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java13
-rw-r--r--core/api/current.txt12
-rw-r--r--core/api/test-current.txt2
-rw-r--r--core/java/android/app/ActivityManagerInternal.java15
-rw-r--r--core/java/android/app/admin/DelegatedAdminReceiver.java26
-rw-r--r--core/java/android/app/admin/DeviceAdminReceiver.java1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java26
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl8
-rw-r--r--core/java/android/app/people/ConversationStatus.java44
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java8
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java4
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java23
-rw-r--r--core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl2
-rw-r--r--core/java/android/hardware/biometrics/PromptInfo.java13
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java4
-rw-r--r--core/java/android/hardware/display/DisplayManager.java64
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java85
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl1
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl2
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl3
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/java/android/view/SurfaceControl.java18
-rw-r--r--core/java/android/widget/RemoteViews.java28
-rw-r--r--core/java/com/android/internal/app/OWNERS7
-rw-r--r--core/java/com/android/internal/widget/ViewPager.java84
-rw-r--r--core/jni/android_view_SurfaceControl.cpp11
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/ids.xml5
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java127
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--libs/WindowManager/Shell/Android.bp31
-rw-r--r--media/java/android/media/AudioRecord.java4
-rw-r--r--packages/SettingsLib/Android.bp11
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java6
-rw-r--r--services/core/java/com/android/server/WatchedIntentResolver.java (renamed from services/core/java/com/android/server/WatchableIntentResolver.java)2
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java40
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java16
-rw-r--r--services/core/java/com/android/server/am/OWNERS4
-rw-r--r--services/core/java/com/android/server/biometrics/AuthSession.java3
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricSensor.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java3
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java61
-rw-r--r--services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java2
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java40
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileIntentResolver.java4
-rw-r--r--services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java4
-rw-r--r--services/core/java/com/android/server/pm/PreferredIntentResolver.java4
-rw-r--r--services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java36
-rw-r--r--services/core/java/com/android/server/wm/LocalAnimationAdapter.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java92
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java218
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java159
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java137
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java42
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/StubTransaction.java5
99 files changed, 1590 insertions, 532 deletions
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 77aa14c37d79..28069743d957 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -37,6 +37,7 @@ import android.os.Bundle;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -58,6 +59,7 @@ public class AppSearchManagerService extends SystemService {
private static final String TAG = "AppSearchManagerService";
private PackageManagerInternal mPackageManagerInternal;
private ImplInstanceManager mImplInstanceManager;
+ private UserManager mUserManager;
// Cache of unlocked user ids so we don't have to query UserManager service each time. The
// "locked" suffix refers to the fact that access to the field should be locked; unrelated to
@@ -74,10 +76,11 @@ public class AppSearchManagerService extends SystemService {
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mImplInstanceManager = ImplInstanceManager.getInstance(getContext());
+ mUserManager = getContext().getSystemService(UserManager.class);
}
@Override
- public void onUserUnlocked(@NonNull TargetUser user) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
synchronized (mUnlockedUserIdsLocked) {
mUnlockedUserIdsLocked.add(user.getUserIdentifier());
}
@@ -509,7 +512,13 @@ public class AppSearchManagerService extends SystemService {
private void verifyUserUnlocked(int callingUserId) {
synchronized (mUnlockedUserIdsLocked) {
- if (!mUnlockedUserIdsLocked.contains(callingUserId)) {
+ // First, check the local copy.
+ if (mUnlockedUserIdsLocked.contains(callingUserId)) {
+ return;
+ }
+ // If the local copy says the user is locked, check with UM for the actual state,
+ // since the user might just have been unlocked.
+ if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId))) {
throw new IllegalStateException(
"User " + callingUserId + " is locked or not running.");
}
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 2ce85ee57205..8c06338560bf 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -136,6 +136,23 @@ public interface AppStandbyInternal {
void restrictApp(@NonNull String packageName, int userId,
@SystemForcedReasons int restrictReason);
+ /**
+ * Put the specified app in the
+ * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
+ * bucket. If it has been used by the user recently, the restriction will delayed
+ * until an appropriate time. This should only be used in cases where
+ * {@link #restrictApp(String, int, int)} is not sufficient.
+ *
+ * @param mainReason The main reason for restricting the app. Must be either {@link
+ * android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_SYSTEM} or
+ * {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_USER}.
+ * Calls providing any other value will be ignored.
+ * @param restrictReason The restrictReason for restricting the app. Should be one of the
+ * UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons.
+ */
+ void restrictApp(@NonNull String packageName, int userId, int mainReason,
+ @SystemForcedReasons int restrictReason);
+
void addActiveDeviceAdmin(String adminPkg, int userId);
void setActiveAdminApps(Set<String> adminPkgs, int userId);
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 82f2f69bbde5..2b08ba554404 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -793,6 +793,13 @@ public class JobSchedulerService extends com.android.server.SystemService
mDebuggableApps.remove(pkgName);
}
}
+ } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ synchronized (mLock) {
+ for (int c = 0; c < mControllers.size(); ++c) {
+ mControllers.get(c).onUserAddedLocked(userId);
+ }
+ }
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (DEBUG) {
@@ -1454,6 +1461,7 @@ public class JobSchedulerService extends com.android.server.SystemService
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_ADDED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
try {
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 784c63a6cf1f..2b79969f4378 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
@@ -28,6 +28,7 @@ import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -42,7 +43,9 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManagerInternal;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Handler;
@@ -118,6 +121,10 @@ public final class QuotaController extends StateController {
private static final String ALARM_TAG_CLEANUP = "*job.cleanup*";
private static final String ALARM_TAG_QUOTA_CHECK = "*job.quota_check*";
+ private static final int SYSTEM_APP_CHECK_FLAGS =
+ PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.GET_PERMISSIONS | PackageManager.MATCH_KNOWN_PACKAGES;
+
/**
* Standardize the output of userId-packageName combo.
*/
@@ -526,7 +533,9 @@ public final class QuotaController extends StateController {
QcConstants.DEFAULT_EJ_LIMIT_RESTRICTED_MS
};
- private long mEjLimitSpecialAdditionMs = QcConstants.DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS;
+ private long mEjLimitAdditionInstallerMs = QcConstants.DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS;
+
+ private long mEjLimitAdditionSpecialMs = QcConstants.DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS;
/**
* The period of time used to calculate expedited job sessions. Apps can only have expedited job
@@ -560,9 +569,11 @@ public final class QuotaController extends StateController {
private long mEJGracePeriodTopAppMs = QcConstants.DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS;
- /** The package verifier app. */
- @Nullable
- private String mPackageVerifier;
+ /**
+ * List of system apps with the {@link android.Manifest.permission#INSTALL_PACKAGES} permission
+ * granted for each user.
+ */
+ private final SparseSetArray<String> mSystemInstallers = new SparseSetArray<>();
/** An app has reached its quota. The message should contain a {@link Package} object. */
@VisibleForTesting
@@ -627,11 +638,8 @@ public final class QuotaController extends StateController {
@Override
public void onSystemServicesReady() {
- String[] pkgNames = LocalServices.getService(PackageManagerInternal.class)
- .getKnownPackageNames(
- PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM);
synchronized (mLock) {
- mPackageVerifier = ArrayUtils.firstOrNull(pkgNames);
+ cacheInstallerPackagesLocked(UserHandle.USER_SYSTEM);
}
}
@@ -731,6 +739,11 @@ public final class QuotaController extends StateController {
}
@Override
+ public void onUserAddedLocked(int userId) {
+ cacheInstallerPackagesLocked(userId);
+ }
+
+ @Override
public void onUserRemovedLocked(int userId) {
mTrackedJobs.delete(userId);
mPkgTimers.delete(userId);
@@ -741,6 +754,7 @@ public final class QuotaController extends StateController {
mExecutionStatsCache.delete(userId);
mEJStats.delete(userId);
mUidToPackageCache.clear();
+ mSystemInstallers.remove(userId);
}
/** Drop all historical stats and stop tracking any active sessions for the specified app. */
@@ -767,6 +781,22 @@ public final class QuotaController extends StateController {
mEJStats.delete(userId, packageName);
}
+ private void cacheInstallerPackagesLocked(int userId) {
+ final List<PackageInfo> packages = mContext.getPackageManager()
+ .getInstalledPackagesAsUser(SYSTEM_APP_CHECK_FLAGS, userId);
+ for (int i = packages.size() - 1; i >= 0; --i) {
+ final PackageInfo pi = packages.get(i);
+ final ApplicationInfo ai = pi.applicationInfo;
+ final int idx = ArrayUtils.indexOf(
+ pi.requestedPermissions, Manifest.permission.INSTALL_PACKAGES);
+
+ if (idx >= 0 && ai != null && PackageManager.PERMISSION_GRANTED
+ == mContext.checkPermission(Manifest.permission.INSTALL_PACKAGES, -1, ai.uid)) {
+ mSystemInstallers.add(UserHandle.getUserId(ai.uid), pi.packageName);
+ }
+ }
+ }
+
private boolean isUidInForeground(int uid) {
if (UserHandle.isCore(uid)) {
return true;
@@ -962,7 +992,8 @@ public final class QuotaController extends StateController {
if (quota.getStandbyBucketLocked() == NEVER_INDEX) {
return 0;
}
- final long limitMs = getEJLimitMsLocked(packageName, quota.getStandbyBucketLocked());
+ final long limitMs =
+ getEJLimitMsLocked(userId, packageName, quota.getStandbyBucketLocked());
long remainingMs = limitMs - quota.getTallyLocked();
// Stale sessions may still be factored into tally. Make sure they're removed.
@@ -1000,10 +1031,11 @@ public final class QuotaController extends StateController {
return remainingMs - timer.getCurrentDuration(sElapsedRealtimeClock.millis());
}
- private long getEJLimitMsLocked(@NonNull final String packageName, final int standbyBucket) {
+ private long getEJLimitMsLocked(final int userId, @NonNull final String packageName,
+ final int standbyBucket) {
final long baseLimitMs = mEJLimitsMs[standbyBucket];
- if (packageName.equals(mPackageVerifier)) {
- return baseLimitMs + mEjLimitSpecialAdditionMs;
+ if (mSystemInstallers.contains(userId, packageName)) {
+ return baseLimitMs + mEjLimitAdditionInstallerMs;
}
return baseLimitMs;
}
@@ -1116,7 +1148,8 @@ public final class QuotaController extends StateController {
final long nowElapsed = sElapsedRealtimeClock.millis();
ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
- final long limitMs = getEJLimitMsLocked(packageName, quota.getStandbyBucketLocked());
+ final long limitMs =
+ getEJLimitMsLocked(userId, packageName, quota.getStandbyBucketLocked());
final long startWindowElapsed = Math.max(0, nowElapsed - mEJLimitWindowSizeMs);
long remainingDeadSpaceMs = remainingExecutionTimeMs;
// Total time looked at where a session wouldn't be phasing out.
@@ -1743,7 +1776,8 @@ public final class QuotaController extends StateController {
inRegularQuotaTimeElapsed = inQuotaTimeElapsed;
}
if (remainingEJQuota <= 0) {
- final long limitMs = getEJLimitMsLocked(packageName, standbyBucket) - mQuotaBufferMs;
+ final long limitMs =
+ getEJLimitMsLocked(userId, packageName, standbyBucket) - mQuotaBufferMs;
long sumMs = 0;
final Timer ejTimer = mEJPkgTimers.get(userId, packageName);
if (ejTimer != null && ejTimer.isActive()) {
@@ -3029,8 +3063,11 @@ public final class QuotaController extends StateController {
static final String KEY_EJ_LIMIT_RESTRICTED_MS =
QC_CONSTANT_PREFIX + "ej_limit_restricted_ms";
@VisibleForTesting
- static final String KEY_EJ_LIMIT_SPECIAL_ADDITION_MS =
- QC_CONSTANT_PREFIX + "ej_limit_special_addition_ms";
+ static final String KEY_EJ_LIMIT_ADDITION_SPECIAL_MS =
+ QC_CONSTANT_PREFIX + "ej_limit_addition_special_ms";
+ @VisibleForTesting
+ static final String KEY_EJ_LIMIT_ADDITION_INSTALLER_MS =
+ QC_CONSTANT_PREFIX + "ej_limit_addition_installer_ms";
@VisibleForTesting
static final String KEY_EJ_WINDOW_SIZE_MS =
QC_CONSTANT_PREFIX + "ej_window_size_ms";
@@ -3098,7 +3135,8 @@ public final class QuotaController extends StateController {
private static final long DEFAULT_EJ_LIMIT_FREQUENT_MS = 10 * MINUTE_IN_MILLIS;
private static final long DEFAULT_EJ_LIMIT_RARE_MS = DEFAULT_EJ_LIMIT_FREQUENT_MS;
private static final long DEFAULT_EJ_LIMIT_RESTRICTED_MS = 5 * MINUTE_IN_MILLIS;
- private static final long DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS = 30 * MINUTE_IN_MILLIS;
+ private static final long DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS = 15 * MINUTE_IN_MILLIS;
+ private static final long DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS = 30 * MINUTE_IN_MILLIS;
private static final long DEFAULT_EJ_WINDOW_SIZE_MS = 24 * HOUR_IN_MILLIS;
private static final long DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS = 30 * SECOND_IN_MILLIS;
private static final long DEFAULT_EJ_REWARD_TOP_APP_MS = 10 * SECOND_IN_MILLIS;
@@ -3303,7 +3341,13 @@ public final class QuotaController extends StateController {
/**
* How much additional EJ quota special, critical apps should get.
*/
- public long EJ_LIMIT_SPECIAL_ADDITION_MS = DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS;
+ public long EJ_LIMIT_ADDITION_SPECIAL_MS = DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS;
+
+ /**
+ * How much additional EJ quota system installers (with the INSTALL_PACKAGES permission)
+ * should get.
+ */
+ public long EJ_LIMIT_ADDITION_INSTALLER_MS = DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS;
/**
* The period of time used to calculate expedited job sessions. Apps can only have expedited
@@ -3369,7 +3413,8 @@ public final class QuotaController extends StateController {
case KEY_EJ_LIMIT_FREQUENT_MS:
case KEY_EJ_LIMIT_RARE_MS:
case KEY_EJ_LIMIT_RESTRICTED_MS:
- case KEY_EJ_LIMIT_SPECIAL_ADDITION_MS:
+ case KEY_EJ_LIMIT_ADDITION_SPECIAL_MS:
+ case KEY_EJ_LIMIT_ADDITION_INSTALLER_MS:
case KEY_EJ_WINDOW_SIZE_MS:
updateEJLimitConstantsLocked();
break;
@@ -3704,7 +3749,8 @@ public final class QuotaController extends StateController {
DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_EJ_LIMIT_ACTIVE_MS, KEY_EJ_LIMIT_WORKING_MS,
KEY_EJ_LIMIT_FREQUENT_MS, KEY_EJ_LIMIT_RARE_MS,
- KEY_EJ_LIMIT_RESTRICTED_MS, KEY_EJ_LIMIT_SPECIAL_ADDITION_MS,
+ KEY_EJ_LIMIT_RESTRICTED_MS, KEY_EJ_LIMIT_ADDITION_SPECIAL_MS,
+ KEY_EJ_LIMIT_ADDITION_INSTALLER_MS,
KEY_EJ_WINDOW_SIZE_MS);
EJ_LIMIT_ACTIVE_MS = properties.getLong(
KEY_EJ_LIMIT_ACTIVE_MS, DEFAULT_EJ_LIMIT_ACTIVE_MS);
@@ -3716,8 +3762,10 @@ public final class QuotaController extends StateController {
KEY_EJ_LIMIT_RARE_MS, DEFAULT_EJ_LIMIT_RARE_MS);
EJ_LIMIT_RESTRICTED_MS = properties.getLong(
KEY_EJ_LIMIT_RESTRICTED_MS, DEFAULT_EJ_LIMIT_RESTRICTED_MS);
- EJ_LIMIT_SPECIAL_ADDITION_MS = properties.getLong(
- KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS);
+ EJ_LIMIT_ADDITION_INSTALLER_MS = properties.getLong(
+ KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS);
+ EJ_LIMIT_ADDITION_SPECIAL_MS = properties.getLong(
+ KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS);
EJ_WINDOW_SIZE_MS = properties.getLong(
KEY_EJ_WINDOW_SIZE_MS, DEFAULT_EJ_WINDOW_SIZE_MS);
@@ -3763,11 +3811,17 @@ public final class QuotaController extends StateController {
mEJLimitsMs[RESTRICTED_INDEX] = newRestrictedLimitMs;
mShouldReevaluateConstraints = true;
}
- // The addition must be in the range [0 minutes, window size - active limit].
- long newSpecialAdditionMs = Math.max(0,
- Math.min(newWindowSizeMs - newActiveLimitMs, EJ_LIMIT_SPECIAL_ADDITION_MS));
- if (mEjLimitSpecialAdditionMs != newSpecialAdditionMs) {
- mEjLimitSpecialAdditionMs = newSpecialAdditionMs;
+ // The additions must be in the range [0 minutes, window size - active limit].
+ long newAdditionInstallerMs = Math.max(0,
+ Math.min(newWindowSizeMs - newActiveLimitMs, EJ_LIMIT_ADDITION_INSTALLER_MS));
+ if (mEjLimitAdditionInstallerMs != newAdditionInstallerMs) {
+ mEjLimitAdditionInstallerMs = newAdditionInstallerMs;
+ mShouldReevaluateConstraints = true;
+ }
+ long newAdditionSpecialMs = Math.max(0,
+ Math.min(newWindowSizeMs - newActiveLimitMs, EJ_LIMIT_ADDITION_SPECIAL_MS));
+ if (mEjLimitAdditionSpecialMs != newAdditionSpecialMs) {
+ mEjLimitAdditionSpecialMs = newAdditionSpecialMs;
mShouldReevaluateConstraints = true;
}
}
@@ -3808,7 +3862,8 @@ public final class QuotaController extends StateController {
pw.print(KEY_EJ_LIMIT_FREQUENT_MS, EJ_LIMIT_FREQUENT_MS).println();
pw.print(KEY_EJ_LIMIT_RARE_MS, EJ_LIMIT_RARE_MS).println();
pw.print(KEY_EJ_LIMIT_RESTRICTED_MS, EJ_LIMIT_RESTRICTED_MS).println();
- pw.print(KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, EJ_LIMIT_SPECIAL_ADDITION_MS).println();
+ pw.print(KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, EJ_LIMIT_ADDITION_INSTALLER_MS).println();
+ pw.print(KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, EJ_LIMIT_ADDITION_SPECIAL_MS).println();
pw.print(KEY_EJ_WINDOW_SIZE_MS, EJ_WINDOW_SIZE_MS).println();
pw.print(KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, EJ_TOP_APP_TIME_CHUNK_SIZE_MS).println();
pw.print(KEY_EJ_REWARD_TOP_APP_MS, EJ_REWARD_TOP_APP_MS).println();
@@ -3945,8 +4000,13 @@ public final class QuotaController extends StateController {
}
@VisibleForTesting
- long getEjLimitSpecialAdditionMs() {
- return mEjLimitSpecialAdditionMs;
+ long getEjLimitAdditionInstallerMs() {
+ return mEjLimitAdditionInstallerMs;
+ }
+
+ @VisibleForTesting
+ long getEjLimitAdditionSpecialMs() {
+ return mEjLimitAdditionSpecialMs;
}
@VisibleForTesting
@@ -4067,6 +4127,12 @@ public final class QuotaController extends StateController {
pw.decreaseIndent();
pw.println();
+ pw.println("Special apps:");
+ pw.increaseIndent();
+ pw.print("System installers", mSystemInstallers.toString());
+ pw.decreaseIndent();
+
+ pw.println();
mTrackedJobs.forEach((jobs) -> {
for (int j = 0; j < jobs.size(); j++) {
final JobStatus js = jobs.valueAt(j);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
index 56b30907b2a1..a33ba5b3f8bc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
@@ -103,6 +103,10 @@ public abstract class StateController {
public void onAppRemovedLocked(String packageName, int uid) {
}
+ /** Called when a user is added to the device. */
+ public void onUserAddedLocked(int userId) {
+ }
+
/** Called when a user is removed from the device. */
public void onUserRemovedLocked(int userId) {
}
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 1a808c9b3c33..24f7b37aedac 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1343,13 +1343,24 @@ public class AppStandbyController
@Override
public void restrictApp(@NonNull String packageName, int userId,
@SystemForcedReasons int restrictReason) {
+ restrictApp(packageName, userId, REASON_MAIN_FORCED_BY_SYSTEM, restrictReason);
+ }
+
+ @Override
+ public void restrictApp(@NonNull String packageName, int userId, int mainReason,
+ @SystemForcedReasons int restrictReason) {
+ if (mainReason != REASON_MAIN_FORCED_BY_SYSTEM
+ && mainReason != REASON_MAIN_FORCED_BY_USER) {
+ Slog.e(TAG, "Tried to restrict app " + packageName + " for an unsupported reason");
+ return;
+ }
// If the package is not installed, don't allow the bucket to be set.
if (!mInjector.isPackageInstalled(packageName, 0, userId)) {
Slog.e(TAG, "Tried to restrict uninstalled app: " + packageName);
return;
}
- final int reason = REASON_MAIN_FORCED_BY_SYSTEM | (REASON_SUB_MASK & restrictReason);
+ final int reason = (REASON_MAIN_MASK & mainReason) | (REASON_SUB_MASK & restrictReason);
final long nowElapsed = mInjector.elapsedRealtime();
final int bucket = mAllowRestrictedBucket ? STANDBY_BUCKET_RESTRICTED : STANDBY_BUCKET_RARE;
setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false);
diff --git a/core/api/current.txt b/core/api/current.txt
index 481850e5c138..9dd3a4be049a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6943,6 +6943,7 @@ package android.app.admin {
method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
method public final void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
+ method public void onSecurityLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent);
}
public final class DeviceAdminInfo implements android.os.Parcelable {
@@ -7020,6 +7021,7 @@ package android.app.admin {
field public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
field public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
field public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
+ field public static final String ACTION_SECURITY_LOGS_AVAILABLE = "android.app.action.SECURITY_LOGS_AVAILABLE";
field public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0; // 0x0
field public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1; // 0x1
field public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
@@ -7315,6 +7317,7 @@ package android.app.admin {
field public static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
field public static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
field public static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
+ field public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
@@ -8006,13 +8009,14 @@ package android.app.people {
method public long getStartTimeMillis();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int ACTIVITY_ANNIVERSARY = 2; // 0x2
+ field public static final int ACTIVITY_AUDIO = 4; // 0x4
field public static final int ACTIVITY_BIRTHDAY = 1; // 0x1
- field public static final int ACTIVITY_GAME = 5; // 0x5
- field public static final int ACTIVITY_LOCATION = 6; // 0x6
- field public static final int ACTIVITY_MEDIA = 4; // 0x4
+ field public static final int ACTIVITY_GAME = 6; // 0x6
+ field public static final int ACTIVITY_LOCATION = 7; // 0x7
field public static final int ACTIVITY_NEW_STORY = 3; // 0x3
field public static final int ACTIVITY_OTHER = 0; // 0x0
- field public static final int ACTIVITY_UPCOMING_BIRTHDAY = 7; // 0x7
+ field public static final int ACTIVITY_UPCOMING_BIRTHDAY = 8; // 0x8
+ field public static final int ACTIVITY_VIDEO = 5; // 0x5
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_BUSY = 1; // 0x1
field public static final int AVAILABILITY_OFFLINE = 2; // 0x2
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 92dada62b264..4be620652bb3 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1035,9 +1035,11 @@ package android.hardware.biometrics {
public class BiometricPrompt {
method @NonNull public java.util.List<java.lang.Integer> getAllowedSensorIds();
+ method public boolean isAllowBackgroundAuthentication();
}
public static class BiometricPrompt.Builder {
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.TEST_BIOMETRIC, "android.permission.USE_BIOMETRIC_INTERNAL"}) public android.hardware.biometrics.BiometricPrompt.Builder setAllowBackgroundAuthentication(boolean);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.TEST_BIOMETRIC, "android.permission.USE_BIOMETRIC_INTERNAL"}) public android.hardware.biometrics.BiometricPrompt.Builder setAllowedSensorIds(@NonNull java.util.List<java.lang.Integer>);
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c812e8e1782a..f7a35143916e 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -450,6 +450,21 @@ public abstract class ActivityManagerInternal {
public abstract boolean hasRunningForegroundService(int uid, int foregroundServiceType);
/**
+ * Returns {@code true} if the given notification channel currently has a
+ * notification associated with a foreground service. This is an AMS check
+ * because that is the source of truth for the FGS state.
+ */
+ public abstract boolean hasForegroundServiceNotification(String pkg, @UserIdInt int userId,
+ String channelId);
+
+ /**
+ * If the given app has any FGSs whose notifications are in the given channel,
+ * stop them.
+ */
+ public abstract void stopForegroundServicesForChannel(String pkg, @UserIdInt int userId,
+ String channelId);
+
+ /**
* Registers the specified {@code processObserver} to be notified of future changes to
* process state.
*/
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index 25b8eab452bf..36097c928bb0 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -18,6 +18,7 @@ package android.app.admin;
import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
+import static android.app.admin.DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI;
@@ -115,6 +116,29 @@ public class DelegatedAdminReceiver extends BroadcastReceiver {
}
/**
+ * Called each time a new batch of security logs can be retrieved. This callback method will
+ * only ever be called when security logging is enabled. The logs can only be retrieved while
+ * security logging is enabled.
+ *
+ * <p>If a secondary user or profile is created, this callback won't be received until all users
+ * become affiliated again (even if security logging is enabled). It will also no longer be
+ * possible to retrieve the security logs. See {@link DevicePolicyManager#setAffiliationIds}.
+ *
+ * <p> This callback is only applicable if the delegated app has
+ * {@link DevicePolicyManager#DELEGATION_SECURITY_LOGGING} capability. Additionally, it must
+ * declare an intent filter for {@link DeviceAdminReceiver#ACTION_SECURITY_LOGS_AVAILABLE} in
+ * the receiver's manifest in order to receive this callback. The default implementation
+ * simply throws {@link UnsupportedOperationException}.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @see DevicePolicyManager#retrieveSecurityLogs
+ */
+ public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
+ throw new UnsupportedOperationException("onSecurityLogsAvailable should be implemented");
+ }
+
+ /**
* Intercept delegated device administrator broadcasts. Implementations should not override
* this method; implement the convenience callbacks for each action instead.
*/
@@ -132,6 +156,8 @@ public class DelegatedAdminReceiver extends BroadcastReceiver {
long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
+ } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
+ onSecurityLogsAvailable(context, intent);
} else {
Log.w(TAG, "Unhandled broadcast: " + action);
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index cccc9294c2d5..747a2de80db0 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -290,7 +290,6 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
/**
* Broadcast action: notify that a new batch of security logs is ready to be collected.
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@BroadcastBehavior(explicitOnly = true)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 594b0051a113..426159f43095 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1905,6 +1905,20 @@ public class DevicePolicyManager {
public static final String DELEGATION_CERT_SELECTION = "delegation-cert-selection";
/**
+ * Grants access to {@link #setSecurityLoggingEnabled}, {@link #isSecurityLoggingEnabled},
+ * {@link #retrieveSecurityLogs}, and {@link #retrievePreRebootSecurityLogs}. Once granted the
+ * delegated app will start receiving {@link DelegatedAdminReceiver#onSecurityLogsAvailable}
+ * callback, and Device owner or Profile Owner will no longer receive the
+ * {@link DeviceAdminReceiver#onSecurityLogsAvailable} callback. There can be at most one app
+ * that has this delegation. If another app already had delegated security logging access, it
+ * will lose the delegation when a new app is delegated.
+ *
+ * <p> Can only be granted by Device Owner or Profile Owner of an organnization owned and
+ * managed profile.
+ */
+ public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
+
+ /**
* No management for current user in-effect. This is the default.
* @hide
*/
@@ -11241,7 +11255,7 @@ public class DevicePolicyManager {
public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setSecurityLoggingEnabled");
try {
- mService.setSecurityLoggingEnabled(admin, enabled);
+ mService.setSecurityLoggingEnabled(admin, mContext.getPackageName(), enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11260,7 +11274,7 @@ public class DevicePolicyManager {
public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isSecurityLoggingEnabled");
try {
- return mService.isSecurityLoggingEnabled(admin);
+ return mService.isSecurityLoggingEnabled(admin, mContext.getPackageName());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11285,10 +11299,12 @@ public class DevicePolicyManager {
* @see #isAffiliatedUser
* @see DeviceAdminReceiver#onSecurityLogsAvailable
*/
+ @SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
throwIfParentInstance("retrieveSecurityLogs");
try {
- ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(
+ admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
@@ -11438,11 +11454,13 @@ public class DevicePolicyManager {
* @see #isAffiliatedUser
* @see #retrieveSecurityLogs
*/
+ @SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
@NonNull ComponentName admin) {
throwIfParentInstance("retrievePreRebootSecurityLogs");
try {
- ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(
+ admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e98720c0d96c..7901791fc7d4 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -386,10 +386,10 @@ interface IDevicePolicyManager {
List<String> getAffiliationIds(in ComponentName admin);
boolean isAffiliatedUser();
- void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
- boolean isSecurityLoggingEnabled(in ComponentName admin);
- ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
- ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
+ void setSecurityLoggingEnabled(in ComponentName admin, String packageName, boolean enabled);
+ boolean isSecurityLoggingEnabled(in ComponentName admin, String packageName);
+ ParceledListSlice retrieveSecurityLogs(in ComponentName admin, String packageName);
+ ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin, String packageName);
long forceNetworkLogs();
long forceSecurityLogs();
diff --git a/core/java/android/app/people/ConversationStatus.java b/core/java/android/app/people/ConversationStatus.java
index d2a0255d572e..d351683386e2 100644
--- a/core/java/android/app/people/ConversationStatus.java
+++ b/core/java/android/app/people/ConversationStatus.java
@@ -36,7 +36,8 @@ public final class ConversationStatus implements Parcelable {
ACTIVITY_BIRTHDAY,
ACTIVITY_ANNIVERSARY,
ACTIVITY_NEW_STORY,
- ACTIVITY_MEDIA,
+ ACTIVITY_AUDIO,
+ ACTIVITY_VIDEO,
ACTIVITY_GAME,
ACTIVITY_LOCATION,
ACTIVITY_UPCOMING_BIRTHDAY
@@ -44,14 +45,47 @@ public final class ConversationStatus implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface ActivityType {}
+ /**
+ * Constant representing that the conversation user is engaged in an activity that cannot be
+ * more specifically represented by another type.
+ */
public static final int ACTIVITY_OTHER = 0;
+ /**
+ * Constant representing that today is the conversation user's birthday.
+ */
public static final int ACTIVITY_BIRTHDAY = 1;
+ /**
+ * Constant representing that the conversation user and the device user are celebrating
+ * and anniversary today.
+ */
public static final int ACTIVITY_ANNIVERSARY = 2;
+ /**
+ * Constant representing that the conversation user has posted a new story.
+ */
public static final int ACTIVITY_NEW_STORY = 3;
- public static final int ACTIVITY_MEDIA = 4;
- public static final int ACTIVITY_GAME = 5;
- public static final int ACTIVITY_LOCATION = 6;
- public static final int ACTIVITY_UPCOMING_BIRTHDAY = 7;
+ /**
+ * Constant representing that the conversation user is listening to music or other audio
+ * like a podcast.
+ */
+ public static final int ACTIVITY_AUDIO = 4;
+ /**
+ * Constant representing that the conversation user is watching video content.
+ */
+ public static final int ACTIVITY_VIDEO = 5;
+ /**
+ * Constant representing that the conversation user is playing a game.
+ */
+ public static final int ACTIVITY_GAME = 6;
+ /**
+ * Constant representing that the conversation user is sharing status with the device user.
+ * Use this to represent a general 'this person is sharing their location with you' status or
+ * a more specific 'this is the current location of this person' status.
+ */
+ public static final int ACTIVITY_LOCATION = 7;
+ /**
+ * Constant representing that the conversation user's birthday is approaching soon.
+ */
+ public static final int ACTIVITY_UPCOMING_BIRTHDAY = 8;
/** @hide */
@IntDef(prefix = { "AVAILABILITY_" }, value = {
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 31781ec79203..1db7e9da0bcb 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1104,6 +1104,14 @@ public final class UsageStatsManager {
break;
case REASON_MAIN_FORCED_BY_USER:
sb.append("f");
+ if (subReason > 0) {
+ // Although not expected and shouldn't happen, this could potentially have a
+ // sub-reason if the system tries to give a reason when applying the
+ // FORCED_BY_USER reason. The sub-reason is undefined (though most likely a
+ // REASON_SUB_FORCED_SYSTEM_FLAG_ sub-reason), but it's better to note it in the
+ // log than to exclude it altogether.
+ sb.append("-").append(Integer.toBinaryString(subReason));
+ }
break;
case REASON_MAIN_PREDICTED:
sb.append("p");
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 8fd0de7dbb39..a6b4b47f0db2 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -520,9 +520,7 @@ public class AppWidgetHostView extends FrameLayout {
return;
}
int layoutId = rvToApply.getLayoutId();
- // If our stale view has been prepared to match active, and the new
- // layout matches, try recycling it
- if (content == null && layoutId == mLayoutId) {
+ if (rvToApply.canRecycleView(mView)) {
try {
rvToApply.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
mColorResources);
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 125824707402..2e51dc4427fe 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -368,6 +368,20 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * @param allow If true, allows authentication when the calling package is not in the
+ * foreground. This is set to false by default.
+ * @return This builder
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ @RequiresPermission(anyOf = {TEST_BIOMETRIC, USE_BIOMETRIC_INTERNAL})
+ public Builder setAllowBackgroundAuthentication(boolean allow) {
+ mPromptInfo.setAllowBackgroundAuthentication(allow);
+ return this;
+ }
+
+ /**
* If set check the Device Policy Manager for disabled biometrics.
*
* @param checkDevicePolicyManager
@@ -620,6 +634,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * @return The value set by {@link Builder#setAllowBackgroundAuthentication(boolean)}
+ * @hide
+ */
+ @TestApi
+ public boolean isAllowBackgroundAuthentication() {
+ return mPromptInfo.isAllowBackgroundAuthentication();
+ }
+
+ /**
* A wrapper class for the cryptographic operations supported by BiometricPrompt.
*
* <p>Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac}, and
diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
index 059bf2622b00..876513f266e8 100644
--- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
@@ -48,7 +48,7 @@ interface IBiometricAuthenticator {
// startPreparedClient().
void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie);
+ int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int cookie);
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index 20c25fb82b4c..339c654f4d2f 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -44,6 +44,7 @@ public class PromptInfo implements Parcelable {
private boolean mDisallowBiometricsIfPolicyExists;
private boolean mReceiveSystemEvents;
@NonNull private List<Integer> mAllowedSensorIds = new ArrayList<>();
+ private boolean mAllowBackgroundAuthentication;
public PromptInfo() {
@@ -64,6 +65,7 @@ public class PromptInfo implements Parcelable {
mDisallowBiometricsIfPolicyExists = in.readBoolean();
mReceiveSystemEvents = in.readBoolean();
mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader());
+ mAllowBackgroundAuthentication = in.readBoolean();
}
public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() {
@@ -99,11 +101,14 @@ public class PromptInfo implements Parcelable {
dest.writeBoolean(mDisallowBiometricsIfPolicyExists);
dest.writeBoolean(mReceiveSystemEvents);
dest.writeList(mAllowedSensorIds);
+ dest.writeBoolean(mAllowBackgroundAuthentication);
}
public boolean containsTestConfigurations() {
if (!mAllowedSensorIds.isEmpty()) {
return true;
+ } else if (mAllowBackgroundAuthentication) {
+ return true;
}
return false;
}
@@ -183,6 +188,10 @@ public class PromptInfo implements Parcelable {
mAllowedSensorIds = sensorIds;
}
+ public void setAllowBackgroundAuthentication(boolean allow) {
+ mAllowBackgroundAuthentication = allow;
+ }
+
// Getters
public CharSequence getTitle() {
@@ -248,4 +257,8 @@ public class PromptInfo implements Parcelable {
public List<Integer> getAllowedSensorIds() {
return mAllowedSensorIds;
}
+
+ public boolean isAllowBackgroundAuthentication() {
+ return mAllowBackgroundAuthentication;
+ }
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a3c6f2f1eafd..b7b1a147c822 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -2030,7 +2030,9 @@ public final class CameraManager {
// Tell listeners that the cameras and torch modes are unavailable and schedule a
// reconnection to camera service. When camera service is reconnected, the camera
// and torch statuses will be updated.
- for (int i = 0; i < mDeviceStatus.size(); i++) {
+ // Iterate from the end to the beginning befcause onStatusChangedLocked removes
+ // entries from the ArrayMap.
+ for (int i = mDeviceStatus.size() - 1; i >= 0; i--) {
String cameraId = mDeviceStatus.keyAt(i);
onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 2c3e7f18a3ab..6dd67447c321 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import android.Manifest;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -376,6 +377,43 @@ public final class DisplayManager {
@TestApi
public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2;
+ /**
+ * @hide
+ */
+ @LongDef(flag = true, prefix = {"EVENT_FLAG_"}, value = {
+ EVENT_FLAG_DISPLAY_ADDED,
+ EVENT_FLAG_DISPLAY_CHANGED,
+ EVENT_FLAG_DISPLAY_REMOVED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EventsMask {}
+
+ /**
+ * Event type for when a new display is added.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0;
+
+ /**
+ * Event type for when a display is removed.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1;
+
+ /**
+ * Event type for when a display is changed.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;
/** @hide */
public DisplayManager(Context context) {
@@ -486,7 +524,7 @@ public final class DisplayManager {
}
/**
- * Registers an display listener to receive notifications about when
+ * Registers a display listener to receive notifications about when
* displays are added, removed or changed.
*
* @param listener The listener to register.
@@ -496,7 +534,29 @@ public final class DisplayManager {
* @see #unregisterDisplayListener
*/
public void registerDisplayListener(DisplayListener listener, Handler handler) {
- mGlobal.registerDisplayListener(listener, handler);
+ registerDisplayListener(listener, handler, EVENT_FLAG_DISPLAY_ADDED
+ | EVENT_FLAG_DISPLAY_CHANGED | EVENT_FLAG_DISPLAY_REMOVED);
+ }
+
+ /**
+ * Registers a display listener to receive notifications about given display event types.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ * @param eventsMask A bitmask of the event types for which this listener is subscribed.
+ *
+ * @see #EVENT_FLAG_DISPLAY_ADDED
+ * @see #EVENT_FLAG_DISPLAY_CHANGED
+ * @see #EVENT_FLAG_DISPLAY_REMOVED
+ * @see #registerDisplayListener(DisplayListener, Handler)
+ * @see #unregisterDisplayListener
+ *
+ * @hide
+ */
+ public void registerDisplayListener(@NonNull DisplayListener listener,
+ @Nullable Handler handler, @EventsMask long eventsMask) {
+ mGlobal.registerDisplayListener(listener, handler, eventsMask);
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 60fe5825d6a1..fd0431c5bc3f 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -16,6 +16,9 @@
package android.hardware.display;
+import static android.hardware.display.DisplayManager.EventsMask;
+
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache;
@@ -42,6 +45,10 @@ import android.view.DisplayAdjustments;
import android.view.DisplayInfo;
import android.view.Surface;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -66,6 +73,14 @@ public final class DisplayManagerGlobal {
// orientation change before the display info cache has actually been invalidated.
private static final boolean USE_CACHE = false;
+ @IntDef(prefix = {"SWITCHING_TYPE_"}, value = {
+ EVENT_DISPLAY_ADDED,
+ EVENT_DISPLAY_CHANGED,
+ EVENT_DISPLAY_REMOVED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisplayEvent {}
+
public static final int EVENT_DISPLAY_ADDED = 1;
public static final int EVENT_DISPLAY_CHANGED = 2;
public static final int EVENT_DISPLAY_REMOVED = 3;
@@ -81,16 +96,17 @@ public final class DisplayManagerGlobal {
private final IDisplayManager mDm;
private DisplayManagerCallback mCallback;
- private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
- new ArrayList<DisplayListenerDelegate>();
+ private @EventsMask long mRegisteredEventsMask = 0;
+ private final ArrayList<DisplayListenerDelegate> mDisplayListeners = new ArrayList<>();
- private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
+ private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<>();
private final ColorSpace mWideColorSpace;
private int[] mDisplayIdCache;
private int mWifiDisplayScanNestCount;
- private DisplayManagerGlobal(IDisplayManager dm) {
+ @VisibleForTesting
+ public DisplayManagerGlobal(IDisplayManager dm) {
mDm = dm;
try {
mWideColorSpace =
@@ -274,18 +290,25 @@ public final class DisplayManagerGlobal {
* If that is still null, a runtime exception will be thrown.
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
- @Nullable Handler handler) {
+ @Nullable Handler handler, @EventsMask long eventsMask) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
+ if (eventsMask == 0) {
+ throw new IllegalArgumentException("The set of events to listen to must not be empty.");
+ }
+
synchronized (mLock) {
int index = findDisplayListenerLocked(listener);
if (index < 0) {
Looper looper = getLooperForHandler(handler);
- mDisplayListeners.add(new DisplayListenerDelegate(listener, looper));
+ mDisplayListeners.add(new DisplayListenerDelegate(listener, looper, eventsMask));
registerCallbackIfNeededLocked();
+ } else {
+ mDisplayListeners.get(index).setEventsMask(eventsMask);
}
+ updateCallbackIfNeededLocked();
}
}
@@ -300,6 +323,7 @@ public final class DisplayManagerGlobal {
DisplayListenerDelegate d = mDisplayListeners.get(index);
d.clearEvents();
mDisplayListeners.remove(index);
+ updateCallbackIfNeededLocked();
}
}
}
@@ -325,18 +349,36 @@ public final class DisplayManagerGlobal {
return -1;
}
+ @EventsMask
+ private int calculateEventsMaskLocked() {
+ int mask = 0;
+ final int numListeners = mDisplayListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mask |= mDisplayListeners.get(i).mEventsMask;
+ }
+ return mask;
+ }
+
private void registerCallbackIfNeededLocked() {
if (mCallback == null) {
mCallback = new DisplayManagerCallback();
+ updateCallbackIfNeededLocked();
+ }
+ }
+
+ private void updateCallbackIfNeededLocked() {
+ int mask = calculateEventsMaskLocked();
+ if (mask != mRegisteredEventsMask) {
try {
- mDm.registerCallback(mCallback);
+ mDm.registerCallbackWithEventMask(mCallback, mask);
+ mRegisteredEventsMask = mask;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
- private void handleDisplayEvent(int displayId, int event) {
+ private void handleDisplayEvent(int displayId, @DisplayEvent int event) {
synchronized (mLock) {
if (USE_CACHE) {
mDisplayInfoCache.remove(displayId);
@@ -754,7 +796,7 @@ public final class DisplayManagerGlobal {
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
@Override
- public void onDisplayEvent(int displayId, int event) {
+ public void onDisplayEvent(int displayId, @DisplayEvent int event) {
if (DEBUG) {
Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
}
@@ -764,13 +806,16 @@ public final class DisplayManagerGlobal {
private static final class DisplayListenerDelegate extends Handler {
public final DisplayListener mListener;
+ public long mEventsMask;
- DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper) {
+ DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper,
+ @EventsMask long eventsMask) {
super(looper, null, true /*async*/);
mListener = listener;
+ mEventsMask = eventsMask;
}
- public void sendDisplayEvent(int displayId, int event) {
+ public void sendDisplayEvent(int displayId, @DisplayEvent int event) {
Message msg = obtainMessage(event, displayId, 0);
sendMessage(msg);
}
@@ -779,17 +824,27 @@ public final class DisplayManagerGlobal {
removeCallbacksAndMessages(null);
}
+ public synchronized void setEventsMask(@EventsMask long newEventsMask) {
+ mEventsMask = newEventsMask;
+ }
+
@Override
- public void handleMessage(Message msg) {
+ public synchronized void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_DISPLAY_ADDED:
- mListener.onDisplayAdded(msg.arg1);
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) {
+ mListener.onDisplayAdded(msg.arg1);
+ }
break;
case EVENT_DISPLAY_CHANGED:
- mListener.onDisplayChanged(msg.arg1);
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0) {
+ mListener.onDisplayChanged(msg.arg1);
+ }
break;
case EVENT_DISPLAY_REMOVED:
- mListener.onDisplayRemoved(msg.arg1);
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
+ mListener.onDisplayRemoved(msg.arg1);
+ }
break;
}
}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index ff8a7208a9f0..dee91445c224 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -38,6 +38,7 @@ interface IDisplayManager {
boolean isUidPresentOnDisplay(int uid, int displayId);
void registerCallback(in IDisplayManagerCallback callback);
+ void registerCallbackWithEventMask(in IDisplayManagerCallback callback, long eventsMask);
// Requires CONFIGURE_WIFI_DISPLAY permission.
// The process must have previously registered a callback.
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 6e7c701ef5ff..0b44150afa4d 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -59,7 +59,7 @@ interface IFaceService {
// startPreparedClient().
void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie);
+ int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int sensorId, int cookie);
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 054c0d0f6513..469e87e2390a 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -62,7 +62,8 @@ interface IFingerprintService {
// by BiometricService. To start authentication after the clients are ready, use
// startPreparedClient().
void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie);
+ IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie,
+ boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int sensorId, int cookie);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f1c80af54cba..52517b07f861 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15806,6 +15806,7 @@ public final class Settings {
* 1: Enabled (All apps will receive the new rules)
* @hide
*/
+ @Readable
public static final String BACKPORT_S_NOTIF_RULES = "backport_s_notif_rules";
/**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0167147a1067..85d4878d044c 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -105,7 +105,6 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeMergeTransaction(long transactionObj,
long otherTransactionObj);
private static native void nativeSetAnimationTransaction(long transactionObj);
- private static native void nativeSetEarlyWakeup(long transactionObj);
private static native void nativeSetEarlyWakeupStart(long transactionObj);
private static native void nativeSetEarlyWakeupEnd(long transactionObj);
@@ -3175,23 +3174,6 @@ public final class SurfaceControl implements Parcelable {
return this;
}
- /**
- * @deprecated use {@link Transaction#setEarlyWakeupStart()}
- *
- * Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
- * transaction. This should be used when the caller thinks that the scene is complex enough
- * that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
- * order not to miss frame deadlines.
- * <p>
- * Corresponds to setting ISurfaceComposer::eEarlyWakeup
- * @hide
- */
- @Deprecated
- public Transaction setEarlyWakeup() {
- nativeSetEarlyWakeup(mNativeObject);
- return this;
- }
-
/**
* Provides a hint to SurfaceFlinger to change its offset so that SurfaceFlinger wakes up
* earlier to compose surfaces. The caller should use this as a hint to SurfaceFlinger
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2b73923fc5f4..319e78807684 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2196,7 +2196,7 @@ public class RemoteViews implements Parcelable, Filter {
int recycledViewIndex = findViewIndexToRecycle(target, rvToApply);
if (recycledViewIndex >= 0) {
View child = target.getChildAt(recycledViewIndex);
- if (getViewLayoutId(child) == rvToApply.getLayoutId()) {
+ if (rvToApply.canRecycleView(child)) {
if (nextChild < recycledViewIndex) {
target.removeViews(nextChild, recycledViewIndex - nextChild);
}
@@ -2254,7 +2254,7 @@ public class RemoteViews implements Parcelable, Filter {
// application are placed before.
ViewTree recycled = target.mChildren.get(recycledViewIndex);
// We can only recycle the view if the layout id is the same.
- if (getViewLayoutId(recycled.mRoot) == rvToApply.getLayoutId()) {
+ if (rvToApply.canRecycleView(recycled.mRoot)) {
if (recycledViewIndex > nextChild) {
target.removeChildren(nextChild, recycledViewIndex - nextChild);
}
@@ -3726,7 +3726,8 @@ public class RemoteViews implements Parcelable, Filter {
*
* The {@code stableId} will be used to identify a potential view to recycled when the remote
* view is inflated. Views can be re-used if inserted in the same order, potentially with
- * some views appearing / disappearing.
+ * some views appearing / disappearing. To be recycled the view must not change the layout
+ * used to inflate it or its view id (see {@link RemoteViews#setViewId}).
*
* Note: if a view is re-used, all the actions will be re-applied on it. However, its properties
* are not reset, so what was applied in previous round will have an effect. As a view may be
@@ -5116,6 +5117,7 @@ public class RemoteViews implements Parcelable, Filter {
View v = inflater.inflate(rv.getLayoutId(), parent, false);
if (mViewId != View.NO_ID) {
v.setId(mViewId);
+ v.setTagInternal(R.id.remote_views_override_id, mViewId);
}
v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
return v;
@@ -5335,6 +5337,24 @@ public class RemoteViews implements Parcelable, Filter {
reapply(context, v, handler, size, colorResources, true);
}
+ /** @hide */
+ public boolean canRecycleView(@Nullable View v) {
+ if (v == null) {
+ return false;
+ }
+ Integer previousLayoutId = (Integer) v.getTag(R.id.widget_frame);
+ if (previousLayoutId == null) {
+ return false;
+ }
+ Integer overrideIdTag = (Integer) v.getTag(R.id.remote_views_override_id);
+ int overrideId = overrideIdTag == null ? View.NO_ID : overrideIdTag;
+ // If mViewId is View.NO_ID, we only recycle if overrideId is also View.NO_ID.
+ // Otherwise, it might be that, on a previous iteration, the view's ID was set to
+ // something else, and it should now be reset to the ID defined in the XML layout file,
+ // whatever it is.
+ return previousLayoutId == getLayoutId() && mViewId == overrideId;
+ }
+
// Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
// should set it to false.
private void reapply(Context context, View v, InteractionHandler handler, SizeF size,
@@ -5347,7 +5367,7 @@ public class RemoteViews implements Parcelable, Filter {
// (orientation or size), we throw an exception, since the layouts may be completely
// unrelated.
if (hasMultipleLayouts()) {
- if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+ if (!rvToApply.canRecycleView(v)) {
throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
" that does not share the same root layout id.");
}
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 7ade05cc6de1..e6c911e5b41d 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -3,6 +3,9 @@ per-file *Resolver* = file:/packages/SystemUI/OWNERS
per-file *Chooser* = file:/packages/SystemUI/OWNERS
per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS
per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS
-per-file IVoice* = file:/core/java/android/service/voice/OWNERS
-per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS
+
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 6f377b9b228a..93cde3ddb72d 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -353,8 +353,8 @@ public class ViewPager extends ViewGroup {
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- mLeftEdge = new EdgeEffect(context);
- mRightEdge = new EdgeEffect(context);
+ mLeftEdge = new EdgeEffect(context, attrs);
+ mRightEdge = new EdgeEffect(context, attrs);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
@@ -387,6 +387,28 @@ public class ViewPager extends ViewGroup {
}
/**
+ * Returns the {@link EdgeEffect#getType()} for the edge effects.
+ * @return the {@link EdgeEffect#getType()} for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ @EdgeEffect.EdgeEffectType
+ public int getEdgeEffectType() {
+ // Both left and right edge have the same edge effect type
+ return mLeftEdge.getType();
+ }
+
+ /**
+ * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+ * @param type The edge effect type to use for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+ mLeftEdge.setType(type);
+ mRightEdge.setType(type);
+ invalidate();
+ }
+
+ /**
* Set a PagerAdapter that will supply views for this pager as needed.
*
* @param adapter Adapter to use
@@ -1891,7 +1913,7 @@ public class ViewPager extends ViewGroup {
}
if (mIsBeingDragged) {
// Scroll to follow the motion event
- if (performDrag(x)) {
+ if (performDrag(x, y)) {
postInvalidateOnAnimation();
}
}
@@ -1918,6 +1940,17 @@ public class ViewPager extends ViewGroup {
mIsBeingDragged = true;
requestParentDisallowInterceptTouchEvent(true);
setScrollState(SCROLL_STATE_DRAGGING);
+ } else if (mLeftEdge.getDistance() != 0
+ || mRightEdge.getDistance() != 0) {
+ // Caught the edge glow animation
+ mIsBeingDragged = true;
+ setScrollState(SCROLL_STATE_DRAGGING);
+ if (mLeftEdge.getDistance() != 0) {
+ mLeftEdge.onPullDistance(0f, 1 - mLastMotionY / getHeight());
+ }
+ if (mRightEdge.getDistance() != 0) {
+ mRightEdge.onPullDistance(0f, mLastMotionY / getHeight());
+ }
} else {
completeScroll(false);
mIsBeingDragged = false;
@@ -2009,7 +2042,7 @@ public class ViewPager extends ViewGroup {
// Scroll to follow the motion event
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(activePointerIndex);
- needsInvalidate |= performDrag(x);
+ needsInvalidate |= performDrag(x, ev.getY(activePointerIndex));
}
break;
case MotionEvent.ACTION_UP:
@@ -2080,12 +2113,43 @@ public class ViewPager extends ViewGroup {
}
}
- private boolean performDrag(float x) {
+ /**
+ * If either of the horizontal edge glows are currently active, this consumes part or all of
+ * deltaX on the edge glow.
+ *
+ * @param deltaX The pointer motion, in pixels, in the horizontal direction, positive
+ * for moving down and negative for moving up.
+ * @param y The vertical position of the pointer.
+ * @return The amount of <code>deltaX</code> that has been consumed by the
+ * edge glow.
+ */
+ private float releaseHorizontalGlow(float deltaX, float y) {
+ // First allow releasing existing overscroll effect:
+ float consumed = 0;
+ float displacement = y / getHeight();
+ float pullDistance = (float) deltaX / getWidth();
+ if (mLeftEdge.getDistance() != 0) {
+ consumed = -mLeftEdge.onPullDistance(-pullDistance, 1 - displacement);
+ } else if (mRightEdge.getDistance() != 0) {
+ consumed = mRightEdge.onPullDistance(pullDistance, displacement);
+ }
+ return consumed * getWidth();
+ }
+
+ private boolean performDrag(float x, float y) {
boolean needsInvalidate = false;
+ final float dX = mLastMotionX - x;
final int width = getPaddedWidth();
- final float deltaX = mLastMotionX - x;
mLastMotionX = x;
+ final float releaseConsumed = releaseHorizontalGlow(dX, y);
+ final float deltaX = dX - releaseConsumed;
+ if (releaseConsumed != 0) {
+ needsInvalidate = true;
+ }
+ if (Math.abs(deltaX) < 0.0001f) { // ignore rounding errors from releaseHorizontalGlow()
+ return needsInvalidate;
+ }
final EdgeEffect startEdge;
final EdgeEffect endEdge;
@@ -2128,14 +2192,14 @@ public class ViewPager extends ViewGroup {
if (scrollStart < startBound) {
if (startAbsolute) {
final float over = startBound - scrollStart;
- startEdge.onPull(Math.abs(over) / width);
+ startEdge.onPullDistance(over / width, 1 - y / getHeight());
needsInvalidate = true;
}
clampedScrollStart = startBound;
} else if (scrollStart > endBound) {
if (endAbsolute) {
final float over = scrollStart - endBound;
- endEdge.onPull(Math.abs(over) / width);
+ endEdge.onPullDistance(over / width, y / getHeight());
needsInvalidate = true;
}
clampedScrollStart = endBound;
@@ -2228,7 +2292,9 @@ public class ViewPager extends ViewGroup {
*/
private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) {
int targetPage;
- if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) {
+ if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity
+ && mLeftEdge.getDistance() == 0 // don't fling while stretched
+ && mRightEdge.getDistance() == 0) {
targetPage = currentPage - (velocity < 0 ? mLeftIncr : 0);
} else {
final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 65b8b988f38b..f54ffc50095b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -498,19 +498,14 @@ static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz, jlong trans
transaction->setAnimationTransaction();
}
-static void nativeSetEarlyWakeup(JNIEnv* env, jclass clazz, jlong transactionObj) {
- auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setEarlyWakeup();
-}
-
static void nativeSetEarlyWakeupStart(JNIEnv* env, jclass clazz, jlong transactionObj) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setExplicitEarlyWakeupStart();
+ transaction->setEarlyWakeupStart();
}
static void nativeSetEarlyWakeupEnd(JNIEnv* env, jclass clazz, jlong transactionObj) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setExplicitEarlyWakeupEnd();
+ transaction->setEarlyWakeupEnd();
}
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -1737,8 +1732,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeMergeTransaction },
{"nativeSetAnimationTransaction", "(J)V",
(void*)nativeSetAnimationTransaction },
- {"nativeSetEarlyWakeup", "(J)V",
- (void*)nativeSetEarlyWakeup },
{"nativeSetEarlyWakeupStart", "(J)V",
(void*)nativeSetEarlyWakeupStart },
{"nativeSetEarlyWakeupEnd", "(J)V",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f6fee880bf2f..b0327a5decee 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -59,6 +59,7 @@
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_call_strength</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
</string-array>
@@ -96,6 +97,7 @@
<string translatable="false" name="status_bar_camera">camera</string>
<string translatable="false" name="status_bar_airplane">airplane</string>
<string translatable="false" name="status_bar_no_calling">no_calling</string>
+ <string translatable="false" name="status_bar_call_strength">call_strength</string>
<string translatable="false" name="status_bar_sensors_off">sensors_off</string>
<string translatable="false" name="status_bar_screen_record">screen_record</string>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 7bc4663d1070..c3b35c81cb66 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -252,5 +252,8 @@
<item type="id" name="remote_views_next_child" />
<!-- View tag associating a view with its stable id for potential recycling. -->
- <item type="id" name = "remote_views_stable_id" />
+ <item type="id" name="remote_views_stable_id" />
+
+ <!-- View tag associating a view with its overridden id, to ensure valid recycling only. -->
+ <item type="id" name="remote_views_override_id" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0228dfd45972..7ea762c2fbbb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4592,7 +4592,7 @@
<string name="color_correction_feature_name">Color Correction</string>
<!-- Title of Reduce Brightness feature, shown in the warning dialog about the accessibility shortcut. [CHAR LIMIT=none] -->
- <string name="reduce_bright_colors_feature_name">Reduce brightness</string>
+ <string name="reduce_bright_colors_feature_name">Extra dim</string>
<!-- Text in toast to alert the user that the accessibility shortcut turned on an accessibility service. [CHAR LIMIT=none] -->
<string name="accessibility_shortcut_enabling_service">Held volume keys. <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> turned on.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0f834933ab70..cdeb71c7f162 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2977,6 +2977,7 @@
<java-symbol type="string" name="status_bar_clock" />
<java-symbol type="string" name="status_bar_airplane" />
<java-symbol type="string" name="status_bar_no_calling" />
+ <java-symbol type="string" name="status_bar_call_strength" />
<java-symbol type="string" name="status_bar_mobile" />
<java-symbol type="string" name="status_bar_ethernet" />
<java-symbol type="string" name="status_bar_vpn" />
@@ -3390,6 +3391,8 @@
<java-symbol type="drawable" name="ic_accessibility_color_correction" />
<java-symbol type="drawable" name="ic_accessibility_magnification" />
+ <java-symbol type="string" name="reduce_bright_colors_feature_name" />
+
<!-- com.android.internal.widget.RecyclerView -->
<java-symbol type="id" name="item_touch_helper_previous_elevation"/>
<java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/>
@@ -4321,8 +4324,11 @@
<java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_allowed" />
<java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_default" />
+ <!-- Ids for RemoteViews -->
<java-symbol type="id" name="remote_views_next_child" />
<java-symbol type="id" name="remote_views_stable_id" />
+ <java-symbol type="id" name="remote_views_override_id" />
+
<!-- View and control prompt -->
<java-symbol type="drawable" name="ic_accessibility_24dp" />
<java-symbol type="string" name="view_and_control_notification_title" />
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
new file mode 100644
index 000000000000..dfc9013e3c05
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DisplayManagerGlobalTest {
+
+ private static final long ALL_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+
+ @Mock
+ private IDisplayManager mDisplayManager;
+
+ @Mock
+ private DisplayManager.DisplayListener mListener;
+
+ @Captor
+ private ArgumentCaptor<IDisplayManagerCallback> mCallbackCaptor;
+
+ private Context mContext;
+ private DisplayManagerGlobal mDisplayManagerGlobal;
+ private Handler mHandler;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ Mockito.when(mDisplayManager.getPreferredWideGamutColorSpaceId()).thenReturn(0);
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mHandler = mContext.getMainThreadHandler();
+ mDisplayManagerGlobal = new DisplayManagerGlobal(mDisplayManager);
+ }
+
+ @Test
+ public void testDisplayListenerIsCalled_WhenDisplayEventOccurs() throws RemoteException {
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler, ALL_DISPLAY_EVENTS);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
+ IDisplayManagerCallback callback = mCallbackCaptor.getValue();
+
+ int displayId = 1;
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+ waitForHandler();
+ Mockito.verify(mListener).onDisplayAdded(eq(displayId));
+ Mockito.verifyNoMoreInteractions(mListener);
+
+ Mockito.reset(mListener);
+ callback.onDisplayEvent(1, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+ waitForHandler();
+ Mockito.verify(mListener).onDisplayChanged(eq(displayId));
+ Mockito.verifyNoMoreInteractions(mListener);
+
+ Mockito.reset(mListener);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ waitForHandler();
+ Mockito.verify(mListener).onDisplayRemoved(eq(displayId));
+ Mockito.verifyNoMoreInteractions(mListener);
+ }
+
+ @Test
+ public void testDisplayListenerIsNotCalled_WhenClientIsNotSubscribed() throws RemoteException {
+ // First we subscribe to all events in order to test that the subsequent calls to
+ // registerDisplayListener will update the event mask.
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler, ALL_DISPLAY_EVENTS);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
+ IDisplayManagerCallback callback = mCallbackCaptor.getValue();
+
+ int displayId = 1;
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
+ ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+ waitForHandler();
+ Mockito.verifyZeroInteractions(mListener);
+
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
+ ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_CHANGED);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+ waitForHandler();
+ Mockito.verifyZeroInteractions(mListener);
+
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
+ ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ waitForHandler();
+ Mockito.verifyZeroInteractions(mListener);
+ }
+
+ private void waitForHandler() {
+ mHandler.runWithScissors(() -> { }, 0);
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 9b124ced5663..1924e5fd7941 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -493,6 +493,8 @@ applications that come with the platform
<!-- Permission required for hotword detection service CTS tests -->
<permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
<permission name="android.permission.MANAGE_APP_HIBERNATION"/>
+ <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+ <permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 17c9da573a7c..3f03302de474 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -63,13 +63,13 @@ genrule {
],
tools: ["protologtool"],
cmd: "$(location protologtool) transform-protolog-calls " +
- "--protolog-class com.android.internal.protolog.common.ProtoLog " +
- "--protolog-impl-class com.android.wm.shell.protolog.ShellProtoLogImpl " +
- "--protolog-cache-class com.android.wm.shell.protolog.ShellProtoLogCache " +
- "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " +
- "--loggroups-jar $(location :wm_shell_protolog-groups) " +
- "--output-srcjar $(out) " +
- "$(locations :wm_shell-sources)",
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--protolog-impl-class com.android.wm.shell.protolog.ShellProtoLogImpl " +
+ "--protolog-cache-class com.android.wm.shell.protolog.ShellProtoLogCache " +
+ "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " +
+ "--loggroups-jar $(location :wm_shell_protolog-groups) " +
+ "--output-srcjar $(out) " +
+ "$(locations :wm_shell-sources)",
out: ["wm_shell_protolog.srcjar"],
}
@@ -81,14 +81,13 @@ genrule {
],
tools: ["protologtool"],
cmd: "$(location protologtool) generate-viewer-config " +
- "--protolog-class com.android.internal.protolog.common.ProtoLog " +
- "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " +
- "--loggroups-jar $(location :wm_shell_protolog-groups) " +
- "--viewer-conf $(out) " +
- "$(locations :wm_shell-sources)",
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " +
+ "--loggroups-jar $(location :wm_shell_protolog-groups) " +
+ "--viewer-conf $(out) " +
+ "$(locations :wm_shell-sources)",
out: ["wm_shell_protolog.json"],
}
-
// End ProtoLog
java_library {
@@ -113,7 +112,7 @@ android_library {
"res",
],
java_resources: [
- ":generate-wm_shell_protolog.json",
+ ":generate-wm_shell_protolog.json"
],
static_libs: [
"androidx.appcompat_appcompat",
@@ -126,10 +125,10 @@ android_library {
"protolog-lib",
"SettingsLib",
"WindowManager-Shell-proto",
- "jsr330",
+ "jsr330"
],
kotlincflags: ["-Xjvm-default=enable"],
manifest: "AndroidManifest.xml",
- min_sdk_version: "30",
+ min_sdk_version: "26",
}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index d7112d6dfa63..0d613992f300 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -612,7 +612,9 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
}
/**
- * Sets the context the record belongs to.
+ * Sets the context the record belongs to. This context will be used to pull information,
+ * such as attribution tags, which will be associated with the AudioRecord. However, the
+ * context itself will not be retained by the AudioRecord.
* @param context a non-null {@link Context} instance
* @return the same Builder instance.
*/
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 8a3762c91cbe..d6c66b5663af 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -17,8 +17,8 @@ android_library {
// TODO(b/149540986): revert this change.
static_libs: [
- // All other dependent components should be put in
- // "SettingsLibDependenciesWithoutWifiTracker".
+ // All other dependent components should be put in
+ // "SettingsLibDependenciesWithoutWifiTracker".
"WifiTrackerLib",
],
@@ -27,12 +27,9 @@ android_library {
resource_dirs: ["res"],
- srcs: [
- "src/**/*.java",
- "src/**/*.kt",
- ],
+ srcs: ["src/**/*.java", "src/**/*.kt"],
- min_sdk_version: "30",
+ min_sdk_version: "21",
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8d8e442e094b..b86ae6d199d7 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -435,6 +435,9 @@
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
+ <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+ <uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 685896523e36..691d111089b8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -958,8 +958,6 @@
<string name="quick_settings_dark_mode_secondary_label_on_at">On at <xliff:g id="time" example="10 pm">%s</xliff:g></string>
<!-- QuickSettings: Secondary text for when the Dark theme or some other tile will be on until some user-selected time. [CHAR LIMIT=20] -->
<string name="quick_settings_dark_mode_secondary_label_until">Until <xliff:g id="time" example="7 am">%s</xliff:g></string>
- <!-- QuickSettings: Label for the toggle that controls whether Reduce Brightness is enabled. [CHAR LIMIT=NONE] -->
- <string name="quick_settings_reduce_bright_colors_label">Reduce brightness</string>
<!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
<string name="quick_settings_nfc_label">NFC</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index 255fffdb3291..fa2f32fee755 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -99,11 +99,6 @@ public class TransactionCompat {
return this;
}
- @Deprecated
- public TransactionCompat setEarlyWakeup() {
- return this;
- }
-
public TransactionCompat setColor(SurfaceControlCompat surfaceControl, float[] color) {
mTransaction.setColor(surfaceControl.mSurfaceControl, color);
return this;
@@ -118,8 +113,4 @@ public class TransactionCompat {
SurfaceControl relativeTo, int z) {
t.setRelativeLayer(surfaceControl, relativeTo, z);
}
-
- @Deprecated
- public static void setEarlyWakeup(Transaction t) {
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
index 945c9c499401..118f98da11e2 100644
--- a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
+++ b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
@@ -154,7 +154,9 @@ public class DisabledUdfpsController extends ViewController<DisabledUdfpsView> i
@Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
- mRunningFPS = running && biometricSourceType == FINGERPRINT;
+ if (biometricSourceType == FINGERPRINT) {
+ mRunningFPS = running;
+ }
mAuthenticated &= !mRunningFPS;
updateButtonVisibility();
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index c051b695e823..ca2c034c5d32 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -49,7 +49,6 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.util.ScreenshotHelper;
-import com.android.systemui.Dependency;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.recents.Recents;
@@ -140,6 +139,7 @@ public class SystemActions extends SystemUI {
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
private final SystemActionsBroadcastReceiver mReceiver;
+ private final Recents mRecents;
private Locale mLocale;
private final AccessibilityManager mA11yManager;
private final Lazy<StatusBar> mStatusBar;
@@ -150,8 +150,10 @@ public class SystemActions extends SystemUI {
@Inject
public SystemActions(Context context,
NotificationShadeWindowController notificationShadeController,
- Lazy<StatusBar> statusBar) {
+ Lazy<StatusBar> statusBar,
+ Recents recents) {
super(context);
+ mRecents = recents;
mReceiver = new SystemActionsBroadcastReceiver();
mLocale = mContext.getResources().getConfiguration().getLocales().get(0);
mA11yManager = (AccessibilityManager) mContext.getSystemService(
@@ -366,15 +368,15 @@ public class SystemActions extends SystemUI {
}
private void handleRecents() {
- Dependency.get(Recents.class).toggleRecentApps();
+ mRecents.toggleRecentApps();
}
private void handleNotifications() {
- Dependency.get(StatusBar.class).animateExpandNotificationsPanel();
+ mStatusBar.get().animateExpandNotificationsPanel();
}
private void handleQuickSettings() {
- Dependency.get(StatusBar.class).animateExpandSettingsPanel(null);
+ mStatusBar.get().animateExpandSettingsPanel(null);
}
private void handlePowerDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index b9f9b1bc85dd..98b3fe46ff57 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -321,6 +321,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
checkArgument(mSensorProps != null);
+ mStatusBar.setSensorRect(getSensorLocation());
mCoreLayoutParams = new WindowManager.LayoutParams(
// TODO(b/152419866): Use the UDFPS window type when it becomes available.
@@ -367,7 +368,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
*/
public RectF getSensorLocation() {
// This is currently used to calculate the amount of space available for notifications
- // on lockscreen. Keyguard is only shown in portrait mode for now, so this will need to
+ // on lockscreen and for the udfps light reveal animation on keyguard.
+ // Keyguard is only shown in portrait mode for now, so this will need to
// be updated if that ever changes.
return new RectF(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 2c684d688483..f9c2a2aed751 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -19,12 +19,13 @@ package com.android.systemui.people;
import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_MESSAGES;
import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
+import static android.app.people.ConversationStatus.ACTIVITY_AUDIO;
import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
import static android.app.people.ConversationStatus.ACTIVITY_LOCATION;
-import static android.app.people.ConversationStatus.ACTIVITY_MEDIA;
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
import static android.app.people.ConversationStatus.ACTIVITY_UPCOMING_BIRTHDAY;
+import static android.app.people.ConversationStatus.ACTIVITY_VIDEO;
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH;
@@ -496,8 +497,10 @@ public class PeopleSpaceUtils {
return context.getString(R.string.location_status);
case ACTIVITY_NEW_STORY:
return context.getString(R.string.new_story_status);
- case ACTIVITY_MEDIA:
+ case ACTIVITY_VIDEO:
return context.getString(R.string.video_status);
+ case ACTIVITY_AUDIO:
+ return context.getString(R.string.audio_status);
case ACTIVITY_GAME:
return context.getString(R.string.game_status);
default:
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
index 479be659ba10..03a6689bc449 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
@@ -25,8 +25,8 @@ import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.widget.Switch;
+import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -98,14 +98,14 @@ public class ReduceBrightColorsTile extends QSTileImpl<QSTile.BooleanState>
@Override
public CharSequence getTileLabel() {
- return mContext.getString(R.string.quick_settings_reduce_bright_colors_label);
+ return mContext.getString(R.string.reduce_bright_colors_feature_name);
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.value = mReduceBrightColorsController.isReduceBrightColorsActivated();
state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
- state.label = mContext.getString(R.string.quick_settings_reduce_bright_colors_label);
+ state.label = mContext.getString(R.string.reduce_bright_colors_feature_name);
state.expandedAccessibilityClassName = Switch.class.getName();
state.contentDescription = state.label;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index c1feacaba440..563470d1a260 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -82,6 +82,31 @@ object LiftReveal : LightRevealEffect {
}
}
+class CircleReveal(
+ /** X-value of the circle center of the reveal. */
+ val centerX: Float,
+ /** Y-value of the circle center of the reveal. */
+ val centerY: Float,
+ /** Radius of initial state of circle reveal */
+ val startRadius: Float,
+ /** Radius of end state of circle reveal */
+ val endRadius: Float
+) : LightRevealEffect {
+ override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
+ val interpolatedAmount = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(amount)
+ val fadeAmount =
+ LightRevealEffect.getPercentPastThreshold(interpolatedAmount, 0.75f)
+ val radius = startRadius + ((endRadius - startRadius) * interpolatedAmount)
+ scrim.revealGradientEndColorAlpha = 1f - fadeAmount
+ scrim.setRevealGradientBounds(
+ centerX - radius /* left */,
+ centerY - radius /* top */,
+ centerX + radius /* right */,
+ centerY + radius /* bottom */
+ )
+ }
+}
+
class PowerButtonReveal(
/** Approximate Y-value of the center of the power button on the physical device. */
val powerButtonY: Float
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e1199077efb9..3daa2b3e1e64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -132,6 +132,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
mHiddenShelfIconSize = res.getDimensionPixelOffset(R.dimen.hidden_shelf_icon_size);
mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
+ mShelfIcons.setInNotificationIconShelf(true);
if (!mShowNotificationShelf) {
setVisibility(GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 6b144c652c56..25de551d2699 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -152,6 +152,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
private boolean mDozing;
private boolean mOnLockScreen;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+ private boolean mInNotificationIconShelf;
private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1;
private int mCannedAnimationStartIndex = -1;
@@ -702,6 +703,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
mLockScreenMode = lockScreenMode;
}
+ public void setInNotificationIconShelf(boolean inShelf) {
+ mInNotificationIconShelf = inShelf;
+ }
+
public class IconState extends ViewState {
public static final int NO_VALUE = NotificationIconContainer.NO_VALUE;
public float iconAppearAmount = 1.0f;
@@ -813,7 +818,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
}
icon.setVisibleState(visibleState, animationsAllowed);
- icon.setIconColor(mThemedTextColorPrimary,
+ icon.setIconColor(mInNotificationIconShelf ? mThemedTextColorPrimary : iconColor,
needsCannedAnimation && animationsAllowed);
if (animate) {
animateTo(icon, animationProperties);
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 427df5ebbbab..0e1fe22b2454 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -22,6 +22,7 @@ import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -46,6 +47,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -74,6 +76,7 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.RectF;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -179,6 +182,7 @@ import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
+import com.android.systemui.statusbar.CircleReveal;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.FeatureFlags;
@@ -382,6 +386,8 @@ public class StatusBar extends SystemUI implements DemoMode,
private ChargingRippleView mChargingRipple;
private WiredChargingRippleController mChargingRippleAnimationController;
private PowerButtonReveal mPowerButtonReveal;
+ private CircleReveal mCircleReveal;
+ private ValueAnimator mCircleRevealAnimator = ValueAnimator.ofFloat(0f, 1f);
private final Object mQueueLock = new Object();
@@ -1206,7 +1212,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
mChargingRippleAnimationController.setViewHost(mNotificationShadeWindowView);
- if (mFeatureFlags.useNewLockscreenAnimations() && mDozeParameters.getAlwaysOn()) {
+
+ if (mFeatureFlags.useNewLockscreenAnimations()
+ && (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
mLightRevealScrim.setVisibility(View.VISIBLE);
mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
} else {
@@ -3353,6 +3361,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
()-> {
hideKeyguard();
+ if (shouldShowCircleReveal()) {
+ startCircleReveal();
+ }
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
}).start();
}
@@ -3666,15 +3677,16 @@ public class StatusBar extends SystemUI implements DemoMode,
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- final boolean usePowerButtonEffect =
- (isDozing && mWakefulnessLifecycle.getLastSleepReason()
- == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
- || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
- == PowerManager.WAKE_REASON_POWER_BUTTON);
-
- mLightRevealScrim.setRevealEffect(usePowerButtonEffect
- ? mPowerButtonReveal
- : LiftReveal.INSTANCE);
+ if (!isDozing && shouldShowCircleReveal()) {
+ startCircleReveal();
+ } else if ((isDozing && mWakefulnessLifecycle.getLastSleepReason()
+ == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
+ || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
+ == PowerManager.WAKE_REASON_POWER_BUTTON)) {
+ mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
+ } else if (!mCircleRevealAnimator.isRunning()) {
+ mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
+ }
mNotificationsController.requestNotificationUpdate("onDozingChanged");
updateDozingState();
@@ -3684,6 +3696,22 @@ public class StatusBar extends SystemUI implements DemoMode,
Trace.endSection();
}
+ private void startCircleReveal() {
+ mLightRevealScrim.setRevealEffect(mCircleReveal);
+ mCircleRevealAnimator.cancel();
+ mCircleRevealAnimator.addUpdateListener(animation ->
+ mLightRevealScrim.setRevealAmount(
+ (float) mCircleRevealAnimator.getAnimatedValue()));
+ mCircleRevealAnimator.setDuration(900);
+ mCircleRevealAnimator.start();
+ }
+
+ private boolean shouldShowCircleReveal() {
+ return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
+ && mKeyguardUpdateMonitor.isUdfpsEnrolled()
+ && mBiometricUnlockController.getBiometricType() == FINGERPRINT;
+ }
+
private void updateKeyguardState() {
mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
mStatusBarKeyguardViewManager.isOccluded());
@@ -4170,6 +4198,15 @@ public class StatusBar extends SystemUI implements DemoMode,
mBiometricUnlockController.getBiometricType());
}
+ /**
+ * Set the location of the sensor on UDFPS if existent.
+ */
+ public void setSensorRect(RectF rect) {
+ final float startRadius = (rect.right - rect.left) / 2f;
+ mCircleReveal = new CircleReveal(rect.centerX(), rect.centerY(),
+ startRadius, rect.centerY() - startRadius);
+ }
+
@VisibleForTesting
public void updateScrimController() {
Trace.beginSection("StatusBar#updateScrimController");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 862037617374..8fe9a481ccf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -66,7 +66,11 @@ public interface StatusBarIconController {
/**
* Display the no calling & SMS icons.
*/
- void setCallIndicatorIcons(String slot, List<CallIndicatorIconState> states);
+ void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
+ /**
+ * Display the no calling & SMS icons.
+ */
+ void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
public void setIconVisibility(String slot, boolean b);
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index f0c8527bcb7f..6404aea05a4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -219,27 +219,56 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
}
/**
- * Accept a list of CallIndicatorIconStates, and show them in the same slot
- * @param slot StatusBar slot
+ * Accept a list of CallIndicatorIconStates, and show the call strength icons.
+ * @param slot StatusBar slot for the call strength icons
* @param states All of the no Calling & SMS icon states
*/
@Override
- public void setCallIndicatorIcons(String slot, List<CallIndicatorIconState> states) {
+ public void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states) {
+ Slot callStrengthSlot = getSlot(slot);
+ int callStrengthSlotIndex = getSlotIndex(slot);
+ Collections.reverse(states);
+ for (CallIndicatorIconState state : states) {
+ if (!state.isNoCalling) {
+ StatusBarIconHolder holder = callStrengthSlot.getHolderForTag(state.subId);
+ if (holder == null) {
+ holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state);
+ setIcon(callStrengthSlotIndex, holder);
+ } else {
+ holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithResource(mContext, state.callStrengthResId), 0, 0,
+ state.callStrengthDescription));
+ setIcon(callStrengthSlotIndex, holder);
+ }
+ }
+ setIconVisibility(slot, !state.isNoCalling, state.subId);
+ }
+ }
+
+ /**
+ * Accept a list of CallIndicatorIconStates, and show the no calling icons.
+ * @param slot StatusBar slot for the no calling icons
+ * @param states All of the no Calling & SMS icon states
+ */
+ @Override
+ public void setNoCallingIcons(String slot, List<CallIndicatorIconState> states) {
Slot noCallingSlot = getSlot(slot);
- int slotIndex = getSlotIndex(slot);
+ int noCallingSlotIndex = getSlotIndex(slot);
+ Collections.reverse(states);
for (CallIndicatorIconState state : states) {
- StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId);
- if (holder == null) {
- holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state);
- setIcon(slotIndex, holder);
- } else {
- int resId = state.isNoCalling ? state.noCallingResId : state.callStrengthResId;
- String contentDescription = state.isNoCalling
- ? state.noCallingDescription : state.callStrengthDescription;
- holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
- Icon.createWithResource(mContext, resId), 0, 0, contentDescription));
- setIcon(slotIndex, holder);
+ if (state.isNoCalling) {
+ StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId);
+ if (holder == null) {
+ holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state);
+ setIcon(noCallingSlotIndex, holder);
+ } else {
+ holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithResource(mContext, state.noCallingResId), 0, 0,
+ state.noCallingDescription));
+ setIcon(noCallingSlotIndex, holder);
+ }
}
+ setIconVisibility(slot, state.isNoCalling, state.subId);
}
}
@@ -282,9 +311,15 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
}
}
+ /** */
public void setIconVisibility(String slot, boolean visibility) {
+ setIconVisibility(slot, visibility, 0);
+ }
+
+ /** */
+ public void setIconVisibility(String slot, boolean visibility, int tag) {
int index = getSlotIndex(slot);
- StatusBarIconHolder holder = getIcon(index, 0);
+ StatusBarIconHolder holder = getIcon(index, tag);
if (holder == null || holder.isVisible() == visibility) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index a1a2d30e9b00..19db02a71777 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -83,7 +83,6 @@ public class StatusBarIconHolder {
holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
Icon.createWithResource(context, resId), 0, 0, contentDescription);
holder.mTag = state.subId;
- holder.setVisible(true);
return holder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 9ee7b09589d8..3445826eefbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -50,6 +50,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
private final String mSlotEthernet;
private final String mSlotVpn;
private final String mSlotNoCalling;
+ private final String mSlotCallStrength;
private final Context mContext;
private final StatusBarIconController mIconController;
@@ -83,6 +84,8 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling);
+ mSlotCallStrength =
+ mContext.getString(com.android.internal.R.string.status_bar_call_strength);
mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
@@ -212,8 +215,10 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
state.callStrengthResId = statusIcon.icon;
state.callStrengthDescription = statusIcon.contentDescription;
}
- mIconController.setCallIndicatorIcons(
- mSlotNoCalling, CallIndicatorIconState.copyStates(mCallIndicatorStates));
+ mIconController.setCallStrengthIcons(mSlotCallStrength,
+ CallIndicatorIconState.copyStates(mCallIndicatorStates));
+ mIconController.setNoCallingIcons(mSlotNoCalling,
+ CallIndicatorIconState.copyStates(mCallIndicatorStates));
}
@Override
@@ -300,6 +305,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
mIconController.removeAllIconsForSlot(mSlotMobile);
mIconController.removeAllIconsForSlot(mSlotNoCalling);
+ mIconController.removeAllIconsForSlot(mSlotCallStrength);
mMobileStates.clear();
List<CallIndicatorIconState> noCallingStates = new ArrayList<CallIndicatorIconState>();
noCallingStates.addAll(mCallIndicatorStates);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 6032e51ab554..979951409aa9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -30,8 +30,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
@@ -99,7 +99,7 @@ public class ReduceBrightColorsTileTest extends SysuiTestCase {
assertEquals(Tile.STATE_INACTIVE, mTile.getState().state);
assertEquals(mTile.getState().label.toString(),
- mContext.getString(R.string.quick_settings_reduce_bright_colors_label));
+ mContext.getString(R.string.reduce_bright_colors_feature_name));
}
@Test
@@ -110,7 +110,7 @@ public class ReduceBrightColorsTileTest extends SysuiTestCase {
assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
assertEquals(mTile.getState().label.toString(),
- mContext.getString(R.string.quick_settings_reduce_bright_colors_label));
+ mContext.getString(R.string.reduce_bright_colors_feature_name));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 203ece9532ef..8ad6271bfc7e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -66,7 +66,11 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
}
@Override
- public void setCallIndicatorIcons(String slot, List<CallIndicatorIconState> states) {
+ public void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states) {
+ }
+
+ @Override
+ public void setNoCallingIcons(String slot, List<CallIndicatorIconState> states) {
}
@Override
diff --git a/services/core/java/com/android/server/WatchableIntentResolver.java b/services/core/java/com/android/server/WatchedIntentResolver.java
index 2ef94f17e5d9..e514f3c6fd59 100644
--- a/services/core/java/com/android/server/WatchableIntentResolver.java
+++ b/services/core/java/com/android/server/WatchedIntentResolver.java
@@ -31,7 +31,7 @@ import java.util.List;
* @param <R> The resolver type.
* {@hide}
*/
-public abstract class WatchableIntentResolver<F, R extends Object>
+public abstract class WatchedIntentResolver<F, R extends Object>
extends IntentResolver<F, R>
implements Watchable {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3c445ae4b667..1b352c728554 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -160,6 +160,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
@@ -559,6 +560,45 @@ public final class ActiveServices {
return smap != null ? smap.mStartingBackground.size() >= mMaxStartingBackground : false;
}
+ boolean hasForegroundServiceNotificationLocked(String pkg, int userId, String channelId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Channel u" + userId + "/pkg=" + pkg
+ + "/channelId=" + channelId
+ + " has fg service notification");
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ void stopForegroundServicesForChannelLocked(String pkg, int userId, String channelId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Stopping FGS u" + userId + "/pkg=" + pkg
+ + "/channelId=" + channelId
+ + " for conversation channel clear");
+ }
+ stopServiceLocked(sr, false);
+ }
+ }
+ }
+ }
+ }
+
private ServiceMap getServiceMapLocked(int callingUser) {
ServiceMap smap = mServiceMap.get(callingUser);
if (smap == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0e8644a6569e..c4548a3070a7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15911,6 +15911,22 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public boolean hasForegroundServiceNotification(String pkg, int userId,
+ String channelId) {
+ synchronized (ActivityManagerService.this) {
+ return mServices.hasForegroundServiceNotificationLocked(pkg, userId, channelId);
+ }
+ }
+
+ @Override
+ public void stopForegroundServicesForChannel(String pkg, int userId,
+ String channelId) {
+ synchronized (ActivityManagerService.this) {
+ mServices.stopForegroundServicesForChannelLocked(pkg, userId, channelId);
+ }
+ }
+
+ @Override
public void registerProcessObserver(IProcessObserver processObserver) {
ActivityManagerService.this.registerProcessObserver(processObserver);
}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 9e79b02f8c96..273b9c3430b7 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -30,6 +30,10 @@ per-file BatteryExternalStats* = file:/BATTERY_STATS_OWNERS
michaelwr@google.com
narayan@google.com
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index f88820083768..5083c5ecd1ec 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -195,7 +195,8 @@ public final class AuthSession implements IBinder.DeathRecipient {
final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
final boolean requireConfirmation = isConfirmationRequired(sensor);
sensor.goToStateWaitingForCookie(requireConfirmation, mToken, mOperationId,
- mUserId, mSensorReceiver, mOpPackageName, cookie);
+ mUserId, mSensorReceiver, mOpPackageName, cookie,
+ mPromptInfo.isAllowBackgroundAuthentication());
}
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java
index 85de81bb3491..c9e148f9b6ff 100644
--- a/services/core/java/com/android/server/biometrics/BiometricSensor.java
+++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java
@@ -103,11 +103,12 @@ public abstract class BiometricSensor {
void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie)
+ int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mCookie = cookie;
impl.prepareForAuthentication(requireConfirmation, token,
- sessionId, userId, sensorReceiver, opPackageName, mCookie);
+ sessionId, userId, sensorReceiver, opPackageName, mCookie,
+ allowBackgroundAuthentication);
mSensorState = STATE_WAITING_FOR_COOKIE;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 9617bb09e153..79e75b16dbf2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -55,7 +55,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
@Nullable private final TaskStackListener mTaskStackListener;
private final LockoutTracker mLockoutTracker;
private final boolean mIsRestricted;
- private final boolean mIsKeyguard;
+ private final boolean mAllowBackgroundAuthentication;
protected final long mOperationId;
@@ -68,7 +68,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
- @NonNull LockoutTracker lockoutTracker, boolean isKeyguard) {
+ @NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
mIsStrongBiometric = isStrongBiometric;
@@ -79,7 +79,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
mTaskStackListener = taskStackListener;
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
- mIsKeyguard = isKeyguard;
+ mAllowBackgroundAuthentication = allowBackgroundAuthentication;
}
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
@@ -120,7 +120,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
}
public boolean isKeyguard() {
- return mIsKeyguard;
+ return Utils.isKeyguard(getContext(), getOwnerString());
}
@Override
@@ -152,9 +152,15 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
pm.incrementAuthForUser(getTargetUserId(), authenticated);
}
+ if (mAllowBackgroundAuthentication) {
+ Slog.w(TAG, "Allowing background authentication,"
+ + " this is allowed only for platform or test invocations");
+ }
+
// Ensure authentication only succeeds if the client activity is on top.
boolean isBackgroundAuth = false;
- if (authenticated && !Utils.isKeyguard(getContext(), getOwnerString())
+ if (!mAllowBackgroundAuthentication && authenticated
+ && !Utils.isKeyguard(getContext(), getOwnerString())
&& !Utils.isSystem(getContext(), getOwnerString())) {
final List<ActivityManager.RunningTaskInfo> tasks =
mActivityTaskManager.getTasks(1);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index 2926260321f1..0002ad249376 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -61,10 +61,10 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, int cookie)
+ String opPackageName, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId,
- userId, sensorReceiver, opPackageName, cookie);
+ userId, sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index a74e2da30077..9f5dc69b404e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -306,7 +306,8 @@ public class FaceService extends SystemService implements BiometricServiceCallba
@Override // Binder call
public void prepareForAuthentication(int sensorId, boolean requireConfirmation,
IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie) {
+ IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie,
+ boolean allowBackgroundAuthentication) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -318,7 +319,7 @@ public class FaceService extends SystemService implements BiometricServiceCallba
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
- BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
+ BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 88edfbf12df1..9b6fb0b75c57 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -103,7 +103,8 @@ public interface ServiceProvider {
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
+ @NonNull String opPackageName, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication);
void cancelAuthentication(int sensorId, @NonNull IBinder token);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 089cf1e4cee8..07d173c8da02 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -69,11 +69,11 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
- @NonNull LockoutCache lockoutCache, boolean isKeyguard) {
+ @NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutCache, isKeyguard);
+ lockoutCache, allowBackgroundAuthentication);
mUsageStats = usageStats;
mLockoutCache = lockoutCache;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 82ad655f5878..ca29057c9888 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -445,7 +445,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
final IFace daemon = getHalInstance();
if (daemon == null) {
@@ -466,7 +466,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
- mUsageStats, mSensors.get(sensorId).getLockoutCache(), isKeyguard);
+ mUsageStats, mSensors.get(sensorId).getLockoutCache(),
+ allowBackgroundAuthentication);
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 55e9a8384a86..d8aaa22e8300 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -638,7 +638,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -646,7 +646,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName,
cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric,
- statsClient, mLockoutTracker, mUsageStats, isKeyguard);
+ statsClient, mLockoutTracker, mUsageStats, allowBackgroundAuthentication);
mScheduler.scheduleClientMonitor(client);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 3ca51d32797e..ff06a4a30a80 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -62,11 +62,11 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
- @NonNull UsageStats usageStats, boolean isKeyguard) {
+ @NonNull UsageStats usageStats, boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutTracker, isKeyguard);
+ lockoutTracker, allowBackgroundAuthentication);
mUsageStats = usageStats;
final Resources resources = getContext().getResources();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
index 9e82ffcfadc6..81096802a78b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
@@ -62,10 +62,10 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, int cookie)
+ String opPackageName, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFingerprintService.prepareForAuthentication(mSensorId, token, operationId, userId,
- sensorReceiver, opPackageName, cookie);
+ sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index aa5afb728a9b..e4397fd158e1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -403,7 +403,7 @@ public class FingerprintService extends SystemService implements BiometricServic
@Override // Binder call
public void prepareForAuthentication(int sensorId, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie) {
+ int cookie, boolean allowBackgroundAuthentication) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -415,7 +415,7 @@ public class FingerprintService extends SystemService implements BiometricServic
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
- BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
+ BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index 0d50499bd02a..c09d2d37de44 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -96,7 +96,8 @@ public interface ServiceProvider {
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
+ @NonNull String opPackageName, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication);
void startPreparedClient(int sensorId, int cookie);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index e2743f624c37..76a47d382e4b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -59,11 +59,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
int sensorId, boolean isStrongBiometric, int statsClient,
@Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
- @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
+ @Nullable IUdfpsOverlayController udfpsOverlayController,
+ boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutCache, isKeyguard);
+ lockoutCache, allowBackgroundAuthentication);
mLockoutCache = lockoutCache;
mUdfpsOverlayController = udfpsOverlayController;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 227f6f6ca9ae..1b5def6c7063 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -469,7 +469,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
final IFingerprint daemon = getHalInstance();
if (daemon == null) {
@@ -491,7 +491,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
- mUdfpsOverlayController, isKeyguard);
+ mUdfpsOverlayController, allowBackgroundAuthentication);
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index f112549002fb..136caeb12111 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -611,7 +611,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -620,7 +620,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mContext, mLazyDaemon, token, listener, userId, operationId, restricted,
opPackageName, cookie, false /* requireConfirmation */,
mSensorProperties.sensorId, isStrongBiometric, statsClient,
- mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, isKeyguard);
+ mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
+ allowBackgroundAuthentication);
mScheduler.scheduleClientMonitor(client);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index db371125478d..97f128748bcc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -59,11 +59,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
int sensorId, boolean isStrongBiometric, int statsClient,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker,
- @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
+ @Nullable IUdfpsOverlayController udfpsOverlayController,
+ boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutTracker, isKeyguard);
+ lockoutTracker, allowBackgroundAuthentication);
mLockoutFrameworkImpl = lockoutTracker;
mUdfpsOverlayController = udfpsOverlayController;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
index 95915b7809f3..1003c26f966e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
@@ -59,7 +59,8 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long sessionId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, int cookie) throws RemoteException {
+ String opPackageName, int cookie, boolean allowBackgroundAuthentication)
+ throws RemoteException {
}
@Override
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 82ca820ec4d7..f8a913aeb7cd 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT;
import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.hardware.display.DisplayManager.EventsMask;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
@@ -28,6 +29,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLI
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
+import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
@@ -125,6 +127,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
/**
@@ -820,14 +823,16 @@ public final class DisplayManagerService extends SystemService {
}
private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid,
- int callingUid) {
+ int callingUid, @EventsMask long eventsMask) {
synchronized (mSyncRoot) {
- if (mCallbacks.get(callingPid) != null) {
- throw new SecurityException("The calling process has already "
- + "registered an IDisplayManagerCallback.");
+ CallbackRecord record = mCallbacks.get(callingPid);
+
+ if (record != null) {
+ record.updateEventsMask(eventsMask);
+ return;
}
- CallbackRecord record = new CallbackRecord(callingPid, callingUid, callback);
+ record = new CallbackRecord(callingPid, callingUid, callback, eventsMask);
try {
IBinder binder = callback.asBinder();
binder.linkToDeath(record, 0);
@@ -1695,7 +1700,7 @@ public final class DisplayManagerService extends SystemService {
}
}
- private void sendDisplayEventLocked(int displayId, int event) {
+ private void sendDisplayEventLocked(int displayId, @DisplayEvent int event) {
Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
mHandler.sendMessage(msg);
}
@@ -1724,7 +1729,8 @@ public final class DisplayManagerService extends SystemService {
// Runs on Handler thread.
// Delivers display event notifications to callbacks.
- private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids, int event) {
+ private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids,
+ @DisplayEvent int event) {
if (DEBUG) {
Slog.d(TAG, "Delivering display event: displayId="
+ displayId + ", event=" + event);
@@ -2059,13 +2065,20 @@ public final class DisplayManagerService extends SystemService {
public final int mPid;
public final int mUid;
private final IDisplayManagerCallback mCallback;
+ private @EventsMask AtomicLong mEventsMask;
public boolean mWifiDisplayScanRequested;
- CallbackRecord(int pid, int uid, IDisplayManagerCallback callback) {
+ CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
+ @EventsMask long eventsMask) {
mPid = pid;
mUid = uid;
mCallback = callback;
+ mEventsMask = new AtomicLong(eventsMask);
+ }
+
+ public void updateEventsMask(@EventsMask long eventsMask) {
+ mEventsMask.set(eventsMask);
}
@Override
@@ -2076,7 +2089,11 @@ public final class DisplayManagerService extends SystemService {
onCallbackDied(this);
}
- public void notifyDisplayEventAsync(int displayId, int event) {
+ public void notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
+ if (!shouldSendEvent(event)) {
+ return;
+ }
+
try {
mCallback.onDisplayEvent(displayId, event);
} catch (RemoteException ex) {
@@ -2085,6 +2102,22 @@ public final class DisplayManagerService extends SystemService {
binderDied();
}
}
+
+ private boolean shouldSendEvent(@DisplayEvent int event) {
+ final long mask = mEventsMask.get();
+ switch (event) {
+ case DisplayManagerGlobal.EVENT_DISPLAY_ADDED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0;
+ case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0;
+ case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0;
+ default:
+ // This should never happen.
+ Slog.e(TAG, "Unknown display event " + event);
+ return true;
+ }
+ }
}
@VisibleForTesting
@@ -2149,6 +2182,14 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public void registerCallback(IDisplayManagerCallback callback) {
+ registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+ }
+
+ @Override // Binder call
+ public void registerCallbackWithEventMask(IDisplayManagerCallback callback,
+ @EventsMask long eventsMask) {
if (callback == null) {
throw new IllegalArgumentException("listener must not be null");
}
@@ -2157,7 +2198,7 @@ public final class DisplayManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- registerCallbackInternal(callback, callingPid, callingUid);
+ registerCallbackInternal(callback, callingPid, callingUid, eventsMask);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java b/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
index b4555f851d4d..7d9b0aa03179 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
@@ -28,7 +28,7 @@ class ColorDisplayShellCommand extends ShellCommand {
+ " Shows this message.\n"
+ " set-saturation LEVEL\n"
+ " Sets the device saturation to the given LEVEL, 0-100 inclusive.\n"
- + " set-layer-saturation CALLER_PACKAGE TARGET_PACKAGE LEVEL\n"
+ + " set-layer-saturation LEVEL CALLER_PACKAGE TARGET_PACKAGE\n"
+ " Sets the saturation LEVEL for all layers of the TARGET_PACKAGE, attributed\n"
+ " to the CALLER_PACKAGE. The lowest LEVEL from any CALLER_PACKAGE is applied.\n";
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e58836659189..eb4f9d305a27 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3576,15 +3576,30 @@ public class NotificationManagerService extends SystemService {
pkg, uid, channelId, conversationId, true, includeDeleted);
}
+ // Returns 'true' if the given channel has a notification associated
+ // with an active foreground service.
+ private void enforceDeletingChannelHasNoFgService(String pkg, int userId,
+ String channelId) {
+ if (mAmi.hasForegroundServiceNotification(pkg, userId, channelId)) {
+ Slog.w(TAG, "Package u" + userId + "/" + pkg
+ + " may not delete notification channel '"
+ + channelId + "' with fg service");
+ throw new SecurityException("Not allowed to delete channel " + channelId
+ + " with a foreground service");
+ }
+ }
+
@Override
public void deleteNotificationChannel(String pkg, String channelId) {
checkCallerIsSystemOrSameApp(pkg);
final int callingUid = Binder.getCallingUid();
+ final int callingUser = UserHandle.getUserId(callingUid);
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
throw new IllegalArgumentException("Cannot delete default channel");
}
+ enforceDeletingChannelHasNoFgService(pkg, callingUser, channelId);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
- UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
+ callingUser, REASON_CHANNEL_BANNED, null);
mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
UserHandle.getUserHandleForUid(callingUid),
@@ -3597,19 +3612,23 @@ public class NotificationManagerService extends SystemService {
public void deleteConversationNotificationChannels(String pkg, int uid,
String conversationId) {
checkCallerIsSystem();
- final int callingUid = Binder.getCallingUid();
List<NotificationChannel> channels =
mPreferencesHelper.getNotificationChannelsByConversationId(
pkg, uid, conversationId);
if (!channels.isEmpty()) {
+ // Preflight for fg service notifications in these channels: do nothing
+ // unless they're all eligible
+ final int appUserId = UserHandle.getUserId(uid);
for (NotificationChannel nc : channels) {
+ final String channelId = nc.getId();
+ mAmi.stopForegroundServicesForChannel(pkg, appUserId, channelId);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, nc.getId(), 0, 0, true,
- UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
- mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, nc.getId());
+ appUserId, REASON_CHANNEL_BANNED, null);
+ mPreferencesHelper.deleteNotificationChannel(pkg, uid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
- UserHandle.getUserHandleForUid(callingUid),
+ UserHandle.getUserHandleForUid(uid),
mPreferencesHelper.getNotificationChannel(
- pkg, callingUid, nc.getId(), true),
+ pkg, uid, channelId, true),
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
}
handleSavePolicyFile();
@@ -3640,13 +3659,20 @@ public class NotificationManagerService extends SystemService {
NotificationChannelGroup groupToDelete =
mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
if (groupToDelete != null) {
+ // Preflight for allowability
+ final int userId = UserHandle.getUserId(callingUid);
+ List<NotificationChannel> groupChannels = groupToDelete.getChannels();
+ for (int i = 0; i < groupChannels.size(); i++) {
+ enforceDeletingChannelHasNoFgService(pkg, userId,
+ groupChannels.get(i).getId());
+ }
List<NotificationChannel> deletedChannels =
mPreferencesHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
for (int i = 0; i < deletedChannels.size(); i++) {
final NotificationChannel deletedChannel = deletedChannels.get(i);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannel.getId(), 0, 0,
true,
- UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
+ userId, REASON_CHANNEL_BANNED,
null);
mListeners.notifyNotificationChannelChanged(pkg,
UserHandle.getUserHandleForUid(callingUid),
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
index aae6ce46de66..791a1057d112 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
@@ -19,7 +19,7 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchableIntentResolver;
+import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import java.util.List;
@@ -28,7 +28,7 @@ import java.util.List;
* Used to find a list of {@link CrossProfileIntentFilter}s that match an intent.
*/
class CrossProfileIntentResolver
- extends WatchableIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
+ extends WatchedIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
implements Snappable {
@Override
protected CrossProfileIntentFilter[] newArray(int size) {
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
index c1bfcac50772..2b11a4297835 100644
--- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -19,11 +19,11 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchableIntentResolver;
+import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
public class PersistentPreferredIntentResolver
- extends WatchableIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity>
+ extends WatchedIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity>
implements Snappable {
@Override
protected PersistentPreferredActivity[] newArray(int size) {
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index 0e3b85ca677a..10a6b3f69fde 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -19,14 +19,14 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchableIntentResolver;
+import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import java.io.PrintWriter;
import java.util.ArrayList;
public class PreferredIntentResolver
- extends WatchableIntentResolver<PreferredActivity, PreferredActivity>
+ extends WatchedIntentResolver<PreferredActivity, PreferredActivity>
implements Snappable {
@Override
protected PreferredActivity[] newArray(int size) {
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index 0c8e36b75425..c8dc1b1ff562 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -146,47 +146,11 @@ public class ArtStatsLogUtils {
uid,
compilationReason,
compilerFilter,
- ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES,
- getDexBytes(path),
- dexMetadataType);
- logger.write(
- sessionId,
- uid,
- compilationReason,
- compilerFilter,
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
compileTime,
dexMetadataType);
}
- private static long getDexBytes(String apkPath) {
- StrictJarFile jarFile = null;
- long dexBytes = 0;
- try {
- jarFile = new StrictJarFile(apkPath,
- /*verify=*/ false,
- /*signatureSchemeRollbackProtectionsEnforced=*/ false);
- Iterator<ZipEntry> it = jarFile.iterator();
- while (it.hasNext()) {
- ZipEntry entry = it.next();
- if (entry.getName().matches("classes(\\d)*[.]dex")) {
- dexBytes += entry.getSize();
- }
- }
- return dexBytes;
- } catch (IOException ignore) {
- Slog.e(TAG, "Error when parsing APK " + apkPath);
- return -1L;
- } finally {
- try {
- if (jarFile != null) {
- jarFile.close();
- }
- } catch (IOException ignore) {
- }
- }
- }
-
private static int getDexMetadataType(String dexMetadataPath) {
if (dexMetadataPath == null) {
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE;
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index f0629fa953fc..520bd8b2108e 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -126,7 +126,7 @@ class LocalAnimationAdapter implements AnimationAdapter {
/**
* @return {@code true} if we need to wake-up SurfaceFlinger earlier during this animation.
*
- * @see Transaction#setEarlyWakeup
+ * @see Transaction#setEarlyWakeupStart and Transaction#setEarlyWakeupEnd
*/
default boolean needsEarlyWakeup() { return false; }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8131e4e00ce..283895bb53e2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_
import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
@@ -430,6 +431,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_INSTALL_EXISTING_PACKAGE,
DELEGATION_KEEP_UNINSTALLED_PACKAGES,
DELEGATION_NETWORK_LOGGING,
+ DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
};
@@ -440,9 +442,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_NETWORK_LOGGING,
});
+ // Subset of delegations that can only be delegated by Device Owner or Profile Owner of an
+ // organization-owned and managed profile.
+ private static final List<String>
+ DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS =
+ Arrays.asList(new String[]{
+ DELEGATION_SECURITY_LOGGING,
+ });
+
// Subset of delegations that only one single package within a given user can hold
private static final List<String> EXCLUSIVE_DELEGATIONS = Arrays.asList(new String[] {
DELEGATION_NETWORK_LOGGING,
+ DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
});
@@ -6024,6 +6035,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!Collections.disjoint(scopes, DEVICE_OWNER_OR_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId())));
+ } else if (!Collections.disjoint(
+ scopes, DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ || isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
@@ -7658,6 +7673,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action,
deviceOwnerUserId);
}
+ if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ receiverComponent = resolveDelegateReceiver(DELEGATION_SECURITY_LOGGING, action,
+ deviceOwnerUserId);
+ }
if (receiverComponent == null) {
synchronized (getLockObject()) {
receiverComponent = mOwners.getDeviceOwnerComponent();
@@ -7674,6 +7693,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId);
}
+ if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ receiverComponent = resolveDelegateReceiver(
+ DELEGATION_SECURITY_LOGGING, action, userId);
+ }
if (receiverComponent == null) {
receiverComponent = getOwnerComponent(userId);
}
@@ -13920,16 +13943,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
+ public void setSecurityLoggingEnabled(ComponentName admin, String packageName,
+ boolean enabled) {
if (!mHasFeature) {
return;
}
- Objects.requireNonNull(admin);
- final CallerIdentity caller = getCallerIdentity(admin);
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
synchronized (getLockObject()) {
- Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
+
if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
return;
}
@@ -13949,17 +13980,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public boolean isSecurityLoggingEnabled(ComponentName admin) {
+ public boolean isSecurityLoggingEnabled(ComponentName admin, String packageName) {
if (!mHasFeature) {
return false;
}
synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
- Objects.requireNonNull(admin);
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(
- isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
}
return mInjector.securityLogGetLoggingEnabledProperty();
}
@@ -13977,15 +14014,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin,
+ String packageName) {
if (!mHasFeature) {
return null;
}
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
+
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
@@ -14015,15 +14060,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin,
+ String packageName) {
if (!mHasFeature) {
return null;
}
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
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 281c1aafe049..f73af535f452 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
@@ -52,6 +52,7 @@ import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
@@ -66,7 +67,10 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ServiceInfo;
import android.os.BatteryManager;
@@ -142,6 +146,8 @@ public class QuotaControllerTest {
@Mock
private JobSchedulerService mJobSchedulerService;
@Mock
+ private PackageManager mPackageManager;
+ @Mock
private PackageManagerInternal mPackageManagerInternal;
@Mock
private PowerAllowlistInternal mPowerAllowlistInternal;
@@ -201,6 +207,8 @@ public class QuotaControllerTest {
-> mDeviceConfigPropertiesBuilder.build())
.when(() -> DeviceConfig.getProperties(
eq(DeviceConfig.NAMESPACE_JOB_SCHEDULER), ArgumentMatchers.<String>any()));
+ // Used in QuotaController.onSystemServicesReady
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
// Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
// in the past, and QuotaController sometimes floors values at 0, so if the test time
@@ -2704,7 +2712,8 @@ public class QuotaControllerTest {
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 1 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 30 * MINUTE_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 27 * MINUTE_IN_MILLIS);
- setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, 10 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, 7 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, 10 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, 12 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 10 * MINUTE_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 87 * SECOND_IN_MILLIS);
@@ -2745,7 +2754,8 @@ public class QuotaControllerTest {
assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
assertEquals(30 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
assertEquals(27 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
- assertEquals(10 * HOUR_IN_MILLIS, mQuotaController.getEjLimitSpecialAdditionMs());
+ assertEquals(7 * HOUR_IN_MILLIS, mQuotaController.getEjLimitAdditionInstallerMs());
+ assertEquals(10 * HOUR_IN_MILLIS, mQuotaController.getEjLimitAdditionSpecialMs());
assertEquals(12 * HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJTopAppTimeChunkSizeMs());
assertEquals(87 * SECOND_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
@@ -2786,7 +2796,8 @@ public class QuotaControllerTest {
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, -1);
- setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, -1);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, -1);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, -1);
@@ -2823,7 +2834,8 @@ public class QuotaControllerTest {
assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
- assertEquals(0, mQuotaController.getEjLimitSpecialAdditionMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionInstallerMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionSpecialMs());
assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
assertEquals(1, mQuotaController.getEJTopAppTimeChunkSizeMs());
assertEquals(10 * SECOND_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
@@ -2858,7 +2870,8 @@ public class QuotaControllerTest {
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 25 * HOUR_IN_MILLIS);
- setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, 25 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, 25 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 25 * HOUR_IN_MILLIS);
@@ -2885,7 +2898,8 @@ public class QuotaControllerTest {
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
- assertEquals(0, mQuotaController.getEjLimitSpecialAdditionMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionInstallerMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionSpecialMs());
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJTopAppTimeChunkSizeMs());
assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
@@ -3957,9 +3971,16 @@ public class QuotaControllerTest {
}
@Test
- public void testGetRemainingEJExecutionTimeLocked_SpecialApp() {
- doReturn(new String[]{SOURCE_PACKAGE}).when(mPackageManagerInternal)
- .getKnownPackageNames(eq(PackageManagerInternal.PACKAGE_VERIFIER), anyInt());
+ public void testGetRemainingEJExecutionTimeLocked_Installer() {
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = SOURCE_PACKAGE;
+ pi.requestedPermissions = new String[]{Manifest.permission.INSTALL_PACKAGES};
+ pi.requestedPermissionsFlags = new int[]{PackageInfo.REQUESTED_PERMISSION_GRANTED};
+ pi.applicationInfo = new ApplicationInfo();
+ pi.applicationInfo.uid = mSourceUid;
+ doReturn(List.of(pi)).when(mPackageManager).getInstalledPackagesAsUser(anyInt(), anyInt());
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext).checkPermission(
+ eq(Manifest.permission.INSTALL_PACKAGES), anyInt(), eq(mSourceUid));
mQuotaController.onSystemServicesReady();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -3980,7 +4001,7 @@ public class QuotaControllerTest {
setStandbyBucket(i);
assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
i == NEVER_INDEX ? 0
- : (limits[i] + mQuotaController.getEjLimitSpecialAdditionMs()
+ : (limits[i] + mQuotaController.getEjLimitAdditionInstallerMs()
- 5 * MINUTE_IN_MILLIS),
mQuotaController.getRemainingEJExecutionTimeLocked(
SOURCE_USER_ID, SOURCE_PACKAGE));
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index a6d146e7ef71..3cbc22654292 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -151,7 +151,8 @@ public class AuthSessionTest {
eq(userId),
eq(mSensorReceiver),
eq(TEST_PACKAGE),
- eq(sensor.getCookie()));
+ eq(sensor.getCookie()),
+ anyBoolean() /* allowBackgroundAuthentication */);
}
final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 0c95e05342c8..abc873766de1 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -456,7 +456,8 @@ public class BiometricServiceTest {
anyInt() /* userId */,
any(IBiometricSensorReceiver.class),
anyString() /* opPackageName */,
- cookieCaptor.capture() /* cookie */);
+ cookieCaptor.capture() /* cookie */,
+ anyBoolean() /* allowBackgroundAuthentication */);
// onReadyForAuthentication, mCurrentAuthSession state OK
mBiometricService.mImpl.onReadyForAuthentication(cookieCaptor.getValue());
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index bc86d1d39b1c..429517251f67 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -93,7 +93,9 @@ public class DisplayManagerServiceTest {
private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
-
+ private static final long ALL_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -355,29 +357,13 @@ public class DisplayManagerServiceTest {
// Find the display id of the added FakeDisplayDevice
DisplayManagerService.BinderService bs = displayManager.new BinderService();
- final int[] displayIds = bs.getDisplayIds();
- assertTrue(displayIds.length > 0);
- int displayId = Display.INVALID_DISPLAY;
- for (int i = 0; i < displayIds.length; i++) {
- DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]);
- if (displayDeviceInfo.equals(ddi)) {
- displayId = displayIds[i];
- break;
- }
- }
- assertFalse(displayId == Display.INVALID_DISPLAY);
-
+ int displayId = getDisplayIdForDisplayDevice(displayManager, bs, displayDevice);
// Setup override DisplayInfo
DisplayInfo overrideInfo = bs.getDisplayInfo(displayId);
displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo);
- Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {
- }, 0 /* now */);
-
- // register display listener callback
- FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
- bs.registerCallback(callback);
+ FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
+ displayManager, bs, displayDevice);
// Simulate DisplayDevice change
DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo();
@@ -387,9 +373,9 @@ public class DisplayManagerServiceTest {
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED);
- handler.runWithScissors(() -> {
- }, 0 /* now */);
- assertTrue(callback.mCalled);
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+ assertTrue(callback.mDisplayChangedCalled);
}
/**
@@ -400,7 +386,7 @@ public class DisplayManagerServiceTest {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {}, 0 /* now */);
+ waitForIdleHandler(handler);
try {
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
@@ -616,7 +602,7 @@ public class DisplayManagerServiceTest {
}
/**
- * Tests that there should be a display change notification if the frame rate overrides
+ * Tests that there is a display change notification if the frame rate override
* list is updated.
*/
@Test
@@ -637,7 +623,7 @@ public class DisplayManagerServiceTest {
new DisplayEventReceiver.FrameRateOverride[]{
new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
});
- assertTrue(callback.mCalled);
+ assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateFrameRateOverride(displayManager, displayDevice,
@@ -645,7 +631,7 @@ public class DisplayManagerServiceTest {
new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
new DisplayEventReceiver.FrameRateOverride(1234, 30f),
});
- assertFalse(callback.mCalled);
+ assertFalse(callback.mDisplayChangedCalled);
updateFrameRateOverride(displayManager, displayDevice,
new DisplayEventReceiver.FrameRateOverride[]{
@@ -653,7 +639,7 @@ public class DisplayManagerServiceTest {
new DisplayEventReceiver.FrameRateOverride(1234, 30f),
new DisplayEventReceiver.FrameRateOverride(5678, 30f),
});
- assertTrue(callback.mCalled);
+ assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateFrameRateOverride(displayManager, displayDevice,
@@ -661,14 +647,14 @@ public class DisplayManagerServiceTest {
new DisplayEventReceiver.FrameRateOverride(1234, 30f),
new DisplayEventReceiver.FrameRateOverride(5678, 30f),
});
- assertTrue(callback.mCalled);
+ assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateFrameRateOverride(displayManager, displayDevice,
new DisplayEventReceiver.FrameRateOverride[]{
new DisplayEventReceiver.FrameRateOverride(5678, 30f),
});
- assertFalse(callback.mCalled);
+ assertFalse(callback.mDisplayChangedCalled);
}
/**
@@ -760,6 +746,136 @@ public class DisplayManagerServiceTest {
/*compatChangeEnabled*/ true);
}
+ /**
+ * Tests that EVENT_DISPLAY_ADDED is sent when a display is added.
+ */
+ @Test
+ public void testShouldNotifyDisplayAdded_WhenNewDisplayDeviceIsAdded() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ // register display listener callback
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ displayManagerBinderService.registerCallbackWithEventMask(callback, ALL_DISPLAY_EVENTS);
+
+ waitForIdleHandler(handler);
+
+ createFakeDisplayDevice(displayManager, new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertFalse(callback.mDisplayRemovedCalled);
+ assertTrue(callback.mDisplayAddedCalled);
+ }
+
+ /**
+ * Tests that EVENT_DISPLAY_ADDED is not sent when a display is added and the
+ * client has a callback which is not subscribed to this event type.
+ */
+ @Test
+ public void testShouldNotNotifyDisplayAdded_WhenClientIsNotSubscribed() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ // register display listener callback
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ long allEventsExceptDisplayAdded = ALL_DISPLAY_EVENTS
+ & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED;
+ displayManagerBinderService.registerCallbackWithEventMask(callback,
+ allEventsExceptDisplayAdded);
+
+ waitForIdleHandler(handler);
+
+ createFakeDisplayDevice(displayManager, new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertFalse(callback.mDisplayRemovedCalled);
+ assertFalse(callback.mDisplayAddedCalled);
+ }
+
+ /**
+ * Tests that EVENT_DISPLAY_REMOVED is sent when a display is removed.
+ */
+ @Test
+ public void testShouldNotifyDisplayRemoved_WhenDisplayDeviceIsRemoved() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
+ new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
+ displayManager, displayManagerBinderService, displayDevice);
+
+ waitForIdleHandler(handler);
+
+ displayManager.getDisplayDeviceRepository()
+ .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertTrue(callback.mDisplayRemovedCalled);
+ assertFalse(callback.mDisplayAddedCalled);
+ }
+
+ /**
+ * Tests that EVENT_DISPLAY_REMOVED is not sent when a display is added and the
+ * client has a callback which is not subscribed to this event type.
+ */
+ @Test
+ public void testShouldNotNotifyDisplayRemoved_WhenClientIsNotSubscribed() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
+ new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ long allEventsExceptDisplayRemoved = ALL_DISPLAY_EVENTS
+ & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+ displayManagerBinderService.registerCallbackWithEventMask(callback,
+ allEventsExceptDisplayRemoved);
+
+ waitForIdleHandler(handler);
+
+ displayManager.getDisplayDeviceRepository()
+ .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertFalse(callback.mDisplayRemovedCalled);
+ assertFalse(callback.mDisplayAddedCalled);
+ }
+
private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
throws Exception {
DisplayManagerService displayManager =
@@ -879,8 +995,7 @@ public class DisplayManagerServiceTest {
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED);
Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {
- }, 0 /* now */);
+ waitForIdleHandler(handler);
}
private void updateFrameRateOverride(DisplayManagerService displayManager,
@@ -906,18 +1021,15 @@ public class DisplayManagerServiceTest {
DisplayManagerService.BinderService displayManagerBinderService,
FakeDisplayDevice displayDevice) {
// Find the display id of the added FakeDisplayDevice
- DisplayDeviceInfo displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();
-
int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
displayDevice);
Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {
- }, 0 /* now */);
+ waitForIdleHandler(handler);
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
- displayManagerBinderService.registerCallback(callback);
+ displayManagerBinderService.registerCallbackWithEventMask(callback, ALL_DISPLAY_EVENTS);
return callback;
}
@@ -951,6 +1063,10 @@ public class DisplayManagerServiceTest {
// Would prefer to call displayManager.onStart() directly here but it performs binderService
// registration which triggers security exceptions when running from a test.
handler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
+ waitForIdleHandler(handler);
+ }
+
+ private void waitForIdleHandler(Handler handler) {
waitForIdleHandler(handler, Duration.ofSeconds(1));
}
@@ -971,21 +1087,41 @@ public class DisplayManagerServiceTest {
private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub {
int mDisplayId;
- boolean mCalled = false;
+ boolean mDisplayAddedCalled = false;
+ boolean mDisplayChangedCalled = false;
+ boolean mDisplayRemovedCalled = false;
FakeDisplayManagerCallback(int displayId) {
mDisplayId = displayId;
}
+ FakeDisplayManagerCallback() {
+ mDisplayId = -1;
+ }
+
@Override
public void onDisplayEvent(int displayId, int event) {
- if (displayId == mDisplayId && event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
- mCalled = true;
+ if (mDisplayId != -1 && displayId != mDisplayId) {
+ return;
+ }
+
+ if (event == DisplayManagerGlobal.EVENT_DISPLAY_ADDED) {
+ mDisplayAddedCalled = true;
+ }
+
+ if (event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
+ mDisplayChangedCalled = true;
+ }
+
+ if (event == DisplayManagerGlobal.EVENT_DISPLAY_REMOVED) {
+ mDisplayRemovedCalled = true;
}
}
public void clear() {
- mCalled = false;
+ mDisplayAddedCalled = false;
+ mDisplayChangedCalled = false;
+ mDisplayRemovedCalled = false;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index 55cd772ad7e0..94e67d16acab 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -23,15 +23,14 @@ import static org.junit.Assert.assertTrue;
import android.content.om.OverlayIdentifier;
import android.content.om.OverlayInfo;
-import android.util.ArraySet;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Arrays;
-import java.util.function.BiConsumer;
+import java.util.Set;
+import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase {
@@ -45,51 +44,47 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
private static final OverlayIdentifier IDENTIFIER2 = new OverlayIdentifier(OVERLAY2);
@Test
- public void testUpdateOverlaysForUser() {
+ public void alwaysInitializeAllPackages() {
final OverlayManagerServiceImpl impl = getImpl();
final String otherTarget = "some.other.target";
addPackage(target(TARGET), USER);
addPackage(target(otherTarget), USER);
addPackage(overlay(OVERLAY, TARGET), USER);
- // do nothing, expect no change
- final ArraySet<PackageAndUser> a = impl.updateOverlaysForUser(USER);
- assertEquals(3, a.size());
- assertTrue(a.containsAll(Arrays.asList(
- new PackageAndUser(TARGET, USER),
- new PackageAndUser(otherTarget, USER),
- new PackageAndUser(OVERLAY, USER))));
-
- final ArraySet<PackageAndUser> b = impl.updateOverlaysForUser(USER);
- assertEquals(3, b.size());
- assertTrue(b.containsAll(Arrays.asList(
- new PackageAndUser(TARGET, USER),
- new PackageAndUser(otherTarget, USER),
- new PackageAndUser(OVERLAY, USER))));
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER),
+ new PackageAndUser(otherTarget, USER),
+ new PackageAndUser(OVERLAY, USER));
+
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
}
@Test
- public void testImmutableEnabledChange() throws Exception {
+ public void testImmutableEnabledChange() {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
- configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER));
+
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertFalse(o1.isEnabled());
assertFalse(o1.isMutable);
- configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_ENABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o2 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o2);
assertTrue(o2.isEnabled());
assertFalse(o2.isMutable);
- configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertFalse(o3.isEnabled());
@@ -97,27 +92,30 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
}
@Test
- public void testMutableEnabledChangeHasNoEffect() throws Exception {
+ public void testMutableEnabledChangeHasNoEffect() {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER));
- impl.updateOverlaysForUser(USER);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertFalse(o1.isEnabled());
assertTrue(o1.isMutable);
- configureSystemOverlay(OVERLAY, true /* mutable */, true /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_ENABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o2 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o2);
assertFalse(o2.isEnabled());
assertTrue(o2.isMutable);
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertFalse(o3.isEnabled());
@@ -125,59 +123,68 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
}
@Test
- public void testMutableEnabledToImmutableEnabled() throws Exception {
+ public void testMutableEnabledToImmutableEnabled() {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
- final BiConsumer<Boolean, Boolean> setOverlay = (mutable, enabled) -> {
- configureSystemOverlay(OVERLAY, mutable, enabled, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER));
+
+ final Consumer<ConfigState> setOverlay = (state -> {
+ configureSystemOverlay(OVERLAY, state, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o);
- assertEquals(enabled, o.isEnabled());
- assertEquals(mutable, o.isMutable);
- };
+ assertEquals(o.isEnabled(), state == ConfigState.IMMUTABLE_ENABLED
+ || state == ConfigState.MUTABLE_ENABLED);
+ assertEquals(o.isMutable, state == ConfigState.MUTABLE_DISABLED
+ || state == ConfigState.MUTABLE_ENABLED);
+ });
// Immutable/enabled -> mutable/enabled
- setOverlay.accept(false /* mutable */, true /* enabled */);
- setOverlay.accept(true /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_ENABLED);
+ setOverlay.accept(ConfigState.MUTABLE_ENABLED);
// Mutable/enabled -> immutable/enabled
- setOverlay.accept(false /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_ENABLED);
// Immutable/enabled -> mutable/disabled
- setOverlay.accept(true /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.MUTABLE_DISABLED);
// Mutable/disabled -> immutable/enabled
- setOverlay.accept(false /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_ENABLED);
// Immutable/enabled -> immutable/disabled
- setOverlay.accept(false /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_DISABLED);
// Immutable/disabled -> mutable/enabled
- setOverlay.accept(true /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.MUTABLE_ENABLED);
// Mutable/enabled -> immutable/disabled
- setOverlay.accept(false /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_DISABLED);
// Immutable/disabled -> mutable/disabled
- setOverlay.accept(true /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.MUTABLE_DISABLED);
// Mutable/disabled -> immutable/disabled
- setOverlay.accept(false /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_DISABLED);
}
@Test
public void testMutablePriorityChange() throws Exception {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
- configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 1 /* priority */);
- impl.updateOverlaysForUser(USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(overlay(OVERLAY2, TARGET), USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.MUTABLE_DISABLED, 1 /* priority */);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER),
+ new PackageAndUser(OVERLAY2, USER));
+
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertEquals(0, o1.priority);
@@ -193,10 +200,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
impl.setEnabled(IDENTIFIER, true, USER);
// Reorder the overlays
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 1 /* priority */);
- configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
-
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 1 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertEquals(1, o3.priority);
@@ -211,13 +217,17 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
@Test
public void testImmutablePriorityChange() throws Exception {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
- configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 1 /* priority */);
- impl.updateOverlaysForUser(USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(overlay(OVERLAY2, TARGET), USER);
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_ENABLED, 0 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.IMMUTABLE_ENABLED, 1 /* priority */);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER),
+ new PackageAndUser(OVERLAY2, USER));
+
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertEquals(0, o1.priority);
@@ -229,10 +239,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
assertTrue(o2.isEnabled());
// Reorder the overlays
- configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 1 /* priority */);
- configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
-
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_ENABLED, 1 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.IMMUTABLE_ENABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertEquals(1, o3.priority);
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index 45f82a36c8ed..f69141db0872 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -65,7 +65,8 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
@Test
public void testGetOverlayInfo() throws Exception {
- installPackage(overlay(OVERLAY, TARGET), USER);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final OverlayManagerServiceImpl impl = getImpl();
final OverlayInfo oi = impl.getOverlayInfo(IDENTIFIER, USER);
@@ -77,9 +78,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
@Test
public void testGetOverlayInfosForTarget() throws Exception {
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- installPackage(overlay(OVERLAY3, TARGET), USER2);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY2, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY3, TARGET), USER2,
+ Set.of(new PackageAndUser(OVERLAY3, USER2), new PackageAndUser(TARGET, USER2)));
final OverlayManagerServiceImpl impl = getImpl();
final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
@@ -102,10 +106,14 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
@Test
public void testGetOverlayInfosForUser() throws Exception {
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- installPackage(overlay(OVERLAY3, TARGET2), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY2, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY3, TARGET2), USER,
+ Set.of(new PackageAndUser(OVERLAY3, USER), new PackageAndUser(TARGET2, USER)));
final OverlayManagerServiceImpl impl = getImpl();
final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
@@ -129,9 +137,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
@Test
public void testPriority() throws Exception {
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- installPackage(overlay(OVERLAY3, TARGET), USER);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY2, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY3, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY3, USER), new PackageAndUser(TARGET, USER)));
final OverlayManagerServiceImpl impl = getImpl();
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
@@ -158,11 +169,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
final OverlayManagerServiceImpl impl = getImpl();
assertNull(impl.getOverlayInfo(IDENTIFIER, USER));
- installPackage(overlay(OVERLAY, TARGET), USER);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
assertState(STATE_MISSING_TARGET, IDENTIFIER, USER);
- final FakeDeviceState.PackageBuilder target = target(TARGET);
- installPackage(target, USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_DISABLED, IDENTIFIER, USER);
assertEquals(impl.setEnabled(IDENTIFIER, true, USER),
@@ -170,32 +182,35 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
assertState(STATE_ENABLED, IDENTIFIER, USER);
// target upgrades do not change the state of the overlay
- upgradePackage(target, USER);
+ upgradeAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)),
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_ENABLED, IDENTIFIER, USER);
- uninstallPackage(TARGET, USER);
+ uninstallAndAssert(TARGET, USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_MISSING_TARGET, IDENTIFIER, USER);
- installPackage(target, USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_ENABLED, IDENTIFIER, USER);
}
@Test
public void testOnOverlayPackageUpgraded() throws Exception {
- final FakeDeviceState.PackageBuilder target = target(TARGET);
- final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
- installPackage(target, USER);
- installPackage(overlay, USER);
- upgradePackage(overlay, USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ upgradeAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)),
+ Set.of(new PackageAndUser(TARGET, USER)));
// upgrade to a version where the overlay has changed its target
- final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
- final Pair<Set<PackageAndUser>, Set<PackageAndUser>> pair = upgradePackage(overlay2, USER);
- assertEquals(pair.first, Set.of(new PackageAndUser(TARGET, USER)));
- assertEquals(
+ upgradeAndAssert(overlay(OVERLAY, TARGET2), USER,
+ Set.of(new PackageAndUser(TARGET, USER)),
Set.of(new PackageAndUser(TARGET, USER),
- new PackageAndUser("some.other.target", USER)),
- pair.second);
+ new PackageAndUser(TARGET2, USER)));
}
@Test
@@ -206,13 +221,15 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
// request succeeded, and there was a change that needs to be
// propagated to the rest of the system
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- assertEquals(impl.setEnabled(IDENTIFIER, true, USER),
+ installAndAssert(target(TARGET), USER,
Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ assertEquals(Set.of(new PackageAndUser(TARGET, USER)),
+ impl.setEnabled(IDENTIFIER, true, USER));
// request succeeded, but nothing changed
- assertTrue(impl.setEnabled(IDENTIFIER, true, USER).isEmpty());
+ assertEquals(Set.of(), impl.setEnabled(IDENTIFIER, true, USER));
}
@Test
@@ -221,16 +238,18 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
reinitializeImpl();
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(CONFIG_SIGNATURE, CONFIG_SIGNATURE & idmap.policies);
}
@Test
@@ -239,45 +258,51 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
reinitializeImpl();
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
@Test
public void testConfigSignaturePolicyNoConfig() throws Exception {
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
@Test
public void testConfigSignaturePolicyNoRefPkg() throws Exception {
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
@Test
@@ -286,8 +311,10 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
reinitializeImpl();
addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
@@ -295,6 +322,6 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
assertTrue(idmapd.idmapExists(overlayPath, USER));
FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 16e03290b1e4..29ff9f4c282c 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -139,8 +139,19 @@ class OverlayManagerServiceImplTestsBase {
mState.add(pkg, userId);
}
- void configureSystemOverlay(String packageName, boolean mutable, boolean enabled,
+ enum ConfigState {
+ IMMUTABLE_DISABLED,
+ IMMUTABLE_ENABLED,
+ MUTABLE_DISABLED,
+ MUTABLE_ENABLED
+ }
+
+ void configureSystemOverlay(@NonNull String packageName, @NonNull ConfigState state,
int priority) {
+ final boolean mutable = state == ConfigState.MUTABLE_DISABLED
+ || state == ConfigState.MUTABLE_ENABLED;
+ final boolean enabled = state == ConfigState.IMMUTABLE_ENABLED
+ || state == ConfigState.MUTABLE_ENABLED;
when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
@@ -154,13 +165,14 @@ class OverlayManagerServiceImplTestsBase {
*
* @throws IllegalStateException if the package is currently installed
*/
- Set<PackageAndUser> installPackage(FakeDeviceState.PackageBuilder pkg, int userId)
+ void installAndAssert(@NonNull FakeDeviceState.PackageBuilder pkg, int userId,
+ @NonNull Set<PackageAndUser> onAddedUpdatedPackages)
throws OperationFailedException {
if (mState.select(pkg.packageName, userId) != null) {
throw new IllegalStateException("package " + pkg.packageName + " already installed");
}
mState.add(pkg, userId);
- return CollectionUtils.emptyIfNull(mImpl.onPackageAdded(pkg.packageName, userId));
+ assertEquals(onAddedUpdatedPackages, mImpl.onPackageAdded(pkg.packageName, userId));
}
/**
@@ -172,25 +184,20 @@ class OverlayManagerServiceImplTestsBase {
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
* {@link android.content.Intent#EXTRA_REPLACING} extra.
*
- * @return the two Optional<PackageAndUser> objects from starting and finishing the upgrade
- *
* @throws IllegalStateException if the package is not currently installed
*/
- Pair<Set<PackageAndUser>, Set<PackageAndUser>> upgradePackage(
- FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException {
+ void upgradeAndAssert(FakeDeviceState.PackageBuilder pkg, int userId,
+ @NonNull Set<PackageAndUser> onReplacingUpdatedPackages,
+ @NonNull Set<PackageAndUser> onReplacedUpdatedPackages)
+ throws OperationFailedException {
final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
if (replacedPackage == null) {
throw new IllegalStateException("package " + pkg.packageName + " not installed");
}
- final Set<PackageAndUser> updatedPackages1 =
- CollectionUtils.emptyIfNull(mImpl.onPackageReplacing(pkg.packageName, userId));
-
+ assertEquals(onReplacingUpdatedPackages, mImpl.onPackageReplacing(pkg.packageName, userId));
mState.add(pkg, userId);
- final Set<PackageAndUser> updatedPackages2 =
- CollectionUtils.emptyIfNull(mImpl.onPackageReplaced(pkg.packageName, userId));
-
- return Pair.create(updatedPackages1, updatedPackages2);
+ assertEquals(onReplacedUpdatedPackages, mImpl.onPackageReplaced(pkg.packageName, userId));
}
/**
@@ -201,13 +208,14 @@ class OverlayManagerServiceImplTestsBase {
*
* @throws IllegalStateException if the package is not currently installed
*/
- Set<PackageAndUser> uninstallPackage(String packageName, int userId) {
+ void uninstallAndAssert(@NonNull String packageName, int userId,
+ @NonNull Set<PackageAndUser> onRemovedUpdatedPackages) {
final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) {
- throw new IllegalStateException("package " + packageName+ " not installed");
+ throw new IllegalStateException("package " + packageName + " not installed");
}
mState.remove(pkg.packageName);
- return CollectionUtils.emptyIfNull(mImpl.onPackageRemoved(packageName, userId));
+ assertEquals(onRemovedUpdatedPackages, mImpl.onPackageRemoved(pkg.packageName, userId));
}
/** Represents the state of packages installed on a fake device. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
index e605d755183f..13d75a77507f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
@@ -245,14 +245,6 @@ public final class ArtStatsLogUtilsTest {
UID,
COMPILATION_REASON,
COMPILER_FILTER,
- ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES,
- DEX_CONTENT.length,
- dexMetadataType);
- inorder.verify(mockLogger).write(
- SESSION_ID,
- UID,
- COMPILATION_REASON,
- COMPILER_FILTER,
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
COMPILE_TIME,
dexMetadataType);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 624c3de650aa..86b162087f61 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -1390,6 +1390,21 @@ public class AppStandbyControllerTests {
}
@Test
+ public void testRestrictApp_MainReason() throws Exception {
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+ REASON_MAIN_DEFAULT);
+ mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD;
+
+ mController.restrictApp(PACKAGE_1, USER_ID, REASON_MAIN_PREDICTED, 0);
+ // Call should be ignored.
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
+
+ mController.restrictApp(PACKAGE_1, USER_ID, REASON_MAIN_FORCED_BY_USER, 0);
+ // Call should go through
+ assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
+ }
+
+ @Test
public void testAddActiveDeviceAdmin() throws Exception {
assertActiveAdmins(USER_ID, (String[]) null);
assertActiveAdmins(USER_ID2, (String[]) null);
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index 6c722499da4b..bb9e24fa6813 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -198,11 +198,6 @@ public class StubTransaction extends SurfaceControl.Transaction {
}
@Override
- public SurfaceControl.Transaction setEarlyWakeup() {
- return this;
- }
-
- @Override
public SurfaceControl.Transaction setMetadata(SurfaceControl sc, int key, int data) {
return this;
}