summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java27
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java285
-rw-r--r--core/api/test-current.txt2
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java2
-rw-r--r--core/java/android/app/ActivityManagerInternal.java3
-rw-r--r--core/java/android/app/LoadedApk.java23
-rw-r--r--core/java/android/hardware/camera2/CameraExtensionCharacteristics.java34
-rw-r--r--core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl3
-rw-r--r--core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl3
-rw-r--r--core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java41
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/values/strings.xml5
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java22
-rw-r--r--libs/hwui/jni/Typeface.cpp102
-rw-r--r--libs/hwui/jni/fonts/Font.cpp54
-rw-r--r--packages/SystemUI/res/layout/udfps_view.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt5
-rw-r--r--packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java64
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java7
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java6
-rw-r--r--services/core/java/com/android/server/biometrics/AuthService.java26
-rw-r--r--services/core/java/com/android/server/biometrics/AuthSession.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java38
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java96
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java6
-rw-r--r--services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java8
-rw-r--r--services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java54
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java22
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java10
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java385
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java24
-rw-r--r--tests/UpdatableSystemFontTest/Android.bp1
-rw-r--r--tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml1
-rw-r--r--tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java53
-rw-r--r--tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java21
54 files changed, 1189 insertions, 385 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index cef065ddac9e..0e9efbcc98b8 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -1536,13 +1536,14 @@ public class DeviceIdleController extends SystemService
@VisibleForTesting
static final int MSG_REPORT_STATIONARY_STATUS = 7;
private static final int MSG_FINISH_IDLE_OP = 8;
- private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS = 9;
private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
@VisibleForTesting
static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
@VisibleForTesting
static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 13;
+ private static final int MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS = 14;
+ private static final int MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS = 15;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -1659,10 +1660,17 @@ public class DeviceIdleController extends SystemService
}
}
} break;
- case MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS: {
+ case MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS: {
final int appId = msg.arg1;
- final boolean added = (msg.arg2 == 1);
- mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, added);
+ final int reasonCode = msg.arg2;
+ final String reason = (String) msg.obj;
+ mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true,
+ reasonCode, reason);
+ } break;
+ case MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS: {
+ final int appId = msg.arg1;
+ mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, false,
+ REASON_UNKNOWN, /* reason= */ null);
} break;
case MSG_SEND_CONSTRAINT_MONITORING: {
final IDeviceIdleConstraint constraint = (IDeviceIdleConstraint) msg.obj;
@@ -2811,14 +2819,15 @@ public class DeviceIdleController extends SystemService
// NPMS needs to update its state synchronously in certain situations so we
// can't have it use the TempAllowlistChangeListener path right now.
// TODO: see if there's a way to simplify/consolidate
- mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS, appId, 1)
- .sendToTarget();
+ mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS, appId,
+ reasonCode, reason).sendToTarget();
}
reportTempWhitelistChangedLocked(uid, true);
}
}
if (informWhitelistChanged) {
- mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true);
+ mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true,
+ reasonCode, reason);
}
}
@@ -2890,8 +2899,8 @@ public class DeviceIdleController extends SystemService
final int appId = UserHandle.getAppId(uid);
updateTempWhitelistAppIdsLocked(uid, false, 0, 0, REASON_UNKNOWN,
reason, INVALID_UID);
- mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS, appId, 0)
- .sendToTarget();
+ mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS, appId,
+ /* unused= */ 0).sendToTarget();
reportTempWhitelistChangedLocked(uid, false);
try {
mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 1169391d2cd2..fe0c7f718bb0 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -136,6 +136,8 @@ import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
@@ -215,9 +217,18 @@ public class AlarmManagerService extends SystemService {
final Object mLock = new Object();
- /** Immutable set of app ids that have requested SCHEDULE_EXACT_ALARM permission.*/
+ /** Immutable set of app ids requesting {@link Manifest.permission#SCHEDULE_EXACT_ALARM} */
@VisibleForTesting
volatile Set<Integer> mExactAlarmCandidates = Collections.emptySet();
+
+ /**
+ * A map from uid to the last op-mode we have seen for
+ * {@link AppOpsManager#OP_SCHEDULE_EXACT_ALARM}
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ SparseIntArray mLastOpScheduleExactAlarm = new SparseIntArray();
+
// List of alarms per uid deferred due to user applied background restrictions on the source app
SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
private long mNextWakeup;
@@ -522,6 +533,9 @@ public class AlarmManagerService extends SystemService {
static final String KEY_MIN_DEVICE_IDLE_FUZZ = "min_device_idle_fuzz";
@VisibleForTesting
static final String KEY_MAX_DEVICE_IDLE_FUZZ = "max_device_idle_fuzz";
+ @VisibleForTesting
+ static final String KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
+ "kill_on_schedule_exact_alarm_revoked";
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
@@ -564,6 +578,8 @@ public class AlarmManagerService extends SystemService {
private static final long DEFAULT_MIN_DEVICE_IDLE_FUZZ = 2 * 60_000;
private static final long DEFAULT_MAX_DEVICE_IDLE_FUZZ = 15 * 60_000;
+ private static final boolean DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = true;
+
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -644,6 +660,13 @@ public class AlarmManagerService extends SystemService {
*/
public long MAX_DEVICE_IDLE_FUZZ = DEFAULT_MAX_DEVICE_IDLE_FUZZ;
+ /**
+ * Whether or not to kill app when the permission
+ * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} is revoked.
+ */
+ public boolean KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
+ DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED;
+
private long mLastAllowWhileIdleWhitelistDuration = -1;
private int mVersion = 0;
@@ -816,6 +839,11 @@ public class AlarmManagerService extends SystemService {
deviceIdleFuzzBoundariesUpdated = true;
}
break;
+ case KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED:
+ KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = properties.getBoolean(
+ KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
+ DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
+ break;
default:
if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
// The quotas need to be updated in order, so we can't just rely
@@ -830,17 +858,24 @@ public class AlarmManagerService extends SystemService {
}
private void updateExactAlarmDenyList(String[] newDenyList) {
+ final Set<String> newSet = Collections.unmodifiableSet(new ArraySet<>(newDenyList));
+ final Set<String> removed = new ArraySet<>(EXACT_ALARM_DENY_LIST);
+ final Set<String> added = new ArraySet<>(newDenyList);
+
+ added.removeAll(EXACT_ALARM_DENY_LIST);
+ removed.removeAll(newSet);
+ if (added.size() > 0) {
+ mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED, added)
+ .sendToTarget();
+ }
+ if (removed.size() > 0) {
+ mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED, removed)
+ .sendToTarget();
+ }
if (newDenyList.length == 0) {
EXACT_ALARM_DENY_LIST = Collections.emptySet();
} else {
- final Set<String> oldSet = EXACT_ALARM_DENY_LIST;
- final Set<String> newlyAdded = new ArraySet<>(newDenyList);
- EXACT_ALARM_DENY_LIST = Collections.unmodifiableSet(new ArraySet<>(newlyAdded));
- newlyAdded.removeAll(oldSet);
- if (newlyAdded.size() > 0) {
- mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_CHANGED, newlyAdded)
- .sendToTarget();
- }
+ EXACT_ALARM_DENY_LIST = newSet;
}
}
@@ -1007,6 +1042,20 @@ public class AlarmManagerService extends SystemService {
pw.print(KEY_EXACT_ALARM_DENY_LIST, EXACT_ALARM_DENY_LIST);
pw.println();
+ pw.print(KEY_MIN_DEVICE_IDLE_FUZZ);
+ pw.print("=");
+ TimeUtils.formatDuration(MIN_DEVICE_IDLE_FUZZ, pw);
+ pw.println();
+
+ pw.print(KEY_MAX_DEVICE_IDLE_FUZZ);
+ pw.print("=");
+ TimeUtils.formatDuration(MAX_DEVICE_IDLE_FUZZ, pw);
+ pw.println();
+
+ pw.print(KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
+ KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
+ pw.println();
+
pw.decreaseIndent();
}
@@ -1667,16 +1716,57 @@ public class AlarmManagerService extends SystemService {
void refreshExactAlarmCandidates() {
final String[] candidates = mLocalPermissionManager.getAppOpPermissionPackages(
Manifest.permission.SCHEDULE_EXACT_ALARM);
- final Set<Integer> appIds = new ArraySet<>(candidates.length);
+ final Set<Integer> newAppIds = new ArraySet<>(candidates.length);
for (final String candidate : candidates) {
final int uid = mPackageManagerInternal.getPackageUid(candidate,
PackageManager.MATCH_ANY_USER, USER_SYSTEM);
if (uid > 0) {
- appIds.add(UserHandle.getAppId(uid));
+ newAppIds.add(UserHandle.getAppId(uid));
+ }
+ }
+ final ArraySet<Integer> removed = new ArraySet<>(mExactAlarmCandidates);
+ removed.removeAll(newAppIds);
+ // This code is only called on package_added and boot. The set {removed} is only expected to
+ // be non-empty when a package was updated and it removed the permission from its manifest.
+ for (int i = 0; i < removed.size(); i++) {
+ final int removedAppId = removed.valueAt(i);
+ synchronized (mLock) {
+ Slog.i(TAG, "App id " + removedAppId + " lost SCHEDULE_EXACT_ALARM on update");
+
+ final Predicate<Alarm> whichAlarms = a -> {
+ if (UserHandle.getAppId(a.uid) != removedAppId || a.windowLength != 0) {
+ return false;
+ }
+ if (!isExactAlarmChangeEnabled(a.packageName, UserHandle.getUserId(a.uid))) {
+ return false;
+ }
+ return a.alarmClock != null || !isExemptFromExactAlarmPermission(a.uid);
+ };
+ removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
}
}
// No need to lock. Assignment is always atomic.
- mExactAlarmCandidates = Collections.unmodifiableSet(appIds);
+ mExactAlarmCandidates = Collections.unmodifiableSet(newAppIds);
+ }
+
+ @Override
+ public void onUserStarting(TargetUser user) {
+ super.onUserStarting(user);
+ final int userId = user.getUserIdentifier();
+ mHandler.post(() -> {
+ for (final int appId : mExactAlarmCandidates) {
+ final int uid = UserHandle.getUid(userId, appId);
+ final AndroidPackage androidPackage = mPackageManagerInternal.getPackage(uid);
+ // It will be null if it is not installed on the starting user.
+ if (androidPackage != null) {
+ final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM,
+ uid, androidPackage.getPackageName());
+ synchronized (mLock) {
+ mLastOpScheduleExactAlarm.put(uid, mode);
+ }
+ }
+ }
+ });
}
@Override
@@ -1706,17 +1796,44 @@ public class AlarmManagerService extends SystemService {
@Override
public void opChanged(int op, int uid, String packageName)
throws RemoteException {
- if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM) {
+ final int userId = UserHandle.getUserId(uid);
+ if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM
+ || !isExactAlarmChangeEnabled(packageName, userId)) {
return;
}
- if (!hasScheduleExactAlarmInternal(packageName, uid)) {
+
+ final boolean requested = mExactAlarmCandidates.contains(
+ UserHandle.getAppId(uid));
+ final boolean denyListed =
+ mConstants.EXACT_ALARM_DENY_LIST.contains(packageName);
+
+ final int newMode = mAppOps.checkOpNoThrow(
+ AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid, packageName);
+
+ final int oldMode;
+ synchronized (mLock) {
+ final int index = mLastOpScheduleExactAlarm.indexOfKey(uid);
+ if (index < 0) {
+ oldMode = AppOpsManager.opToDefaultMode(
+ AppOpsManager.OP_SCHEDULE_EXACT_ALARM);
+ mLastOpScheduleExactAlarm.put(uid, newMode);
+ } else {
+ oldMode = mLastOpScheduleExactAlarm.valueAt(index);
+ mLastOpScheduleExactAlarm.setValueAt(index, newMode);
+ }
+ }
+
+ final boolean hadPermission = getScheduleExactAlarmState(requested,
+ denyListed, oldMode);
+ final boolean hasPermission = getScheduleExactAlarmState(requested,
+ denyListed, newMode);
+
+ if (hadPermission && !hasPermission) {
mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
uid, 0, packageName).sendToTarget();
- } else {
- // TODO(b/187206399) Make sure this won't be sent, if the app
- // already had the appop previously.
+ } else if (!hadPermission && hasPermission) {
sendScheduleExactAlarmPermissionStateChangedBroadcast(
- packageName, UserHandle.getUserId(uid));
+ packageName, userId);
}
}
});
@@ -2256,12 +2373,28 @@ public class AlarmManagerService extends SystemService {
}
}
+ private static boolean getScheduleExactAlarmState(boolean requested, boolean denyListed,
+ int appOpMode) {
+ if (!requested) {
+ return false;
+ }
+ if (appOpMode == AppOpsManager.MODE_DEFAULT) {
+ return !denyListed;
+ }
+ return appOpMode == AppOpsManager.MODE_ALLOWED;
+ }
+
boolean hasScheduleExactAlarmInternal(String packageName, int uid) {
+ // Not using getScheduleExactAlarmState as this can avoid some calls to AppOpsService.
+ // Not using #mLastOpScheduleExactAlarm as it may contain stale values.
+ // No locking needed as all internal containers being queried are immutable.
+
final long start = mStatLogger.getTime();
final boolean hasPermission;
- // No locking needed as all internal containers being queried are immutable.
if (!mExactAlarmCandidates.contains(UserHandle.getAppId(uid))) {
hasPermission = false;
+ } else if (!isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
+ hasPermission = false;
} else {
final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid,
packageName);
@@ -2368,8 +2501,7 @@ public class AlarmManagerService extends SystemService {
} else if (exact || allowWhileIdle) {
final boolean needsPermission;
boolean lowerQuota;
- if (CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
- callingPackage, UserHandle.of(callingUserId))) {
+ if (isExactAlarmChangeEnabled(callingPackage, callingUserId)) {
needsPermission = exact;
lowerQuota = !exact;
idleOptions = exact ? mOptsWithFgs.toBundle() : mOptsWithoutFgs.toBundle();
@@ -2524,6 +2656,11 @@ public class AlarmManagerService extends SystemService {
}
};
+ private static boolean isExactAlarmChangeEnabled(String packageName, int userId) {
+ return CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
+ packageName, UserHandle.of(userId));
+ }
+
void dumpImpl(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
@@ -2673,6 +2810,17 @@ public class AlarmManagerService extends SystemService {
pw.println("App ids requesting SCHEDULE_EXACT_ALARM: " + mExactAlarmCandidates);
pw.println();
+ pw.print("Last OP_SCHEDULE_EXACT_ALARM: [");
+ for (int i = 0; i < mLastOpScheduleExactAlarm.size(); i++) {
+ if (i > 0) {
+ pw.print(", ");
+ }
+ UserHandle.formatUid(pw, mLastOpScheduleExactAlarm.keyAt(i));
+ pw.print(":" + AppOpsManager.modeToName(mLastOpScheduleExactAlarm.valueAt(i)));
+ }
+ pw.println("]");
+
+ pw.println();
pw.println("Next alarm clock information: ");
pw.increaseIndent();
final TreeSet<Integer> users = new TreeSet<>();
@@ -3362,30 +3510,58 @@ public class AlarmManagerService extends SystemService {
}
/**
- * Called when some packages are added to the {@link Constants#EXACT_ALARM_DENY_LIST}, as this
- * may cause some of them to lose their permission.
+ * Called when the {@link Constants#EXACT_ALARM_DENY_LIST}, changes with the packages that
+ * either got added or deleted.
+ * These packages may lose or gain the SCHEDULE_EXACT_ALARM permission.
*
- * Note that these packages don't need to be installed on the device, but if they do have an
- * exact alarm scheduled and they lose the permission, this alarm will be canceled.
+ * Note that these packages don't need to be installed on the device, but if they are and they
+ * do undergo a permission change, we will handle them appropriately.
*
+ * This should not be called with the lock held as it calls out to other services.
* This is not expected to get called frequently.
*/
- void handlePackagesAddedToExactAlarmsDenyListLocked(ArraySet<String> packageNames) {
- Slog.w(TAG, "Packages " + packageNames + " added to the exact alarm deny list.");
- final Predicate<Alarm> whichAlarms = a -> {
- if (!packageNames.contains(a.packageName) || a.windowLength != 0) {
- return false;
- }
- if (!CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
- a.packageName, UserHandle.getUserHandleForUid(a.uid))) {
- return false;
- }
- if (a.alarmClock == null && isExemptFromExactAlarmPermission(a.uid)) {
- return false;
+ void handleChangesToExactAlarmDenyList(ArraySet<String> changedPackages, boolean added) {
+ Slog.w(TAG, "Packages " + changedPackages + (added ? " added to" : " removed from")
+ + " the exact alarm deny list.");
+
+ final int[] startedUserIds = mActivityManagerInternal.getStartedUserIds();
+
+ for (int i = 0; i < changedPackages.size(); i++) {
+ final String changedPackage = changedPackages.valueAt(i);
+ for (final int userId : startedUserIds) {
+ final int uid = mPackageManagerInternal.getPackageUid(changedPackage, 0, userId);
+ if (uid <= 0) {
+ continue;
+ }
+ if (!isExactAlarmChangeEnabled(changedPackage, userId)) {
+ continue;
+ }
+ final int appOpMode;
+ synchronized (mLock) {
+ appOpMode = mLastOpScheduleExactAlarm.get(uid,
+ AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM));
+ }
+ final boolean requested = mExactAlarmCandidates.contains(UserHandle.getAppId(uid));
+
+ // added: true => package was added to the deny list
+ // added: false => package was removed from the deny list
+ final boolean hadPermission = getScheduleExactAlarmState(requested, !added,
+ appOpMode);
+ final boolean hasPermission = getScheduleExactAlarmState(requested, added,
+ appOpMode);
+
+ if (hadPermission == hasPermission) {
+ continue;
+ }
+ if (added) {
+ synchronized (mLock) {
+ removeExactAlarmsOnPermissionRevokedLocked(uid, changedPackage);
+ }
+ } else {
+ sendScheduleExactAlarmPermissionStateChangedBroadcast(changedPackage, userId);
+ }
}
- return !hasScheduleExactAlarmInternal(a.packageName, a.uid);
- };
- removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
+ }
}
/**
@@ -3396,9 +3572,7 @@ public class AlarmManagerService extends SystemService {
*/
void removeExactAlarmsOnPermissionRevokedLocked(int uid, String packageName) {
Slog.w(TAG, "Package " + packageName + ", uid " + uid + " lost SCHEDULE_EXACT_ALARM!");
- if (!CompatChanges.isChangeEnabled(
- AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
- packageName, UserHandle.getUserHandleForUid(uid))) {
+ if (!isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
return;
}
@@ -3409,6 +3583,11 @@ public class AlarmManagerService extends SystemService {
return false;
};
removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
+
+ if (mConstants.KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED) {
+ PermissionManagerService.killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+ "schedule_exact_alarm revoked");
+ }
}
private void removeAlarmsInternalLocked(Predicate<Alarm> whichAlarms, int reason) {
@@ -3535,6 +3714,11 @@ public class AlarmManagerService extends SystemService {
mRemovalHistory.removeAt(i);
}
}
+ for (int i = mLastOpScheduleExactAlarm.size() - 1; i >= 0; i--) {
+ if (UserHandle.getUserId(mLastOpScheduleExactAlarm.keyAt(i)) == userHandle) {
+ mLastOpScheduleExactAlarm.removeAt(i);
+ }
+ }
}
void interactiveStateChangedLocked(boolean interactive) {
@@ -4091,8 +4275,9 @@ public class AlarmManagerService extends SystemService {
public static final int CHARGING_STATUS_CHANGED = 6;
public static final int REMOVE_FOR_CANCELED = 7;
public static final int REMOVE_EXACT_ALARMS = 8;
- public static final int EXACT_ALARM_DENY_LIST_CHANGED = 9;
- public static final int REFRESH_EXACT_ALARM_CANDIDATES = 10;
+ public static final int EXACT_ALARM_DENY_LIST_PACKAGES_ADDED = 9;
+ public static final int EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED = 10;
+ public static final int REFRESH_EXACT_ALARM_CANDIDATES = 11;
AlarmHandler() {
super(Looper.myLooper());
@@ -4179,10 +4364,11 @@ public class AlarmManagerService extends SystemService {
removeExactAlarmsOnPermissionRevokedLocked(uid, packageName);
}
break;
- case EXACT_ALARM_DENY_LIST_CHANGED:
- synchronized (mLock) {
- handlePackagesAddedToExactAlarmsDenyListLocked((ArraySet<String>) msg.obj);
- }
+ case EXACT_ALARM_DENY_LIST_PACKAGES_ADDED:
+ handleChangesToExactAlarmDenyList((ArraySet<String>) msg.obj, true);
+ break;
+ case EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED:
+ handleChangesToExactAlarmDenyList((ArraySet<String>) msg.obj, false);
break;
case REFRESH_EXACT_ALARM_CANDIDATES:
refreshExactAlarmCandidates();
@@ -4349,6 +4535,7 @@ public class AlarmManagerService extends SystemService {
case Intent.ACTION_UID_REMOVED:
mLastPriorityAlarmDispatch.delete(uid);
mRemovalHistory.delete(uid);
+ mLastOpScheduleExactAlarm.delete(uid);
return;
case Intent.ACTION_PACKAGE_REMOVED:
if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 620323976067..5fa75dd68ce0 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -77,7 +77,7 @@ package android.accessibilityservice {
}
public abstract class AccessibilityService extends android.app.Service {
- field public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000; // 0x3e8
+ field public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 333; // 0x14d
}
public class AccessibilityServiceInfo implements android.os.Parcelable {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 483defab43c9..e91209c1a273 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -685,7 +685,7 @@ public abstract class AccessibilityService extends Service {
* @hide
*/
@TestApi
- public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000;
+ public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 333;
/** @hide */
public static final String KEY_ACCESSIBILITY_SCREENSHOT_STATUS =
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 7cb8bc0d80fd..317e51c27d90 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -254,6 +254,9 @@ public abstract class ActivityManagerInternal {
/** Returns the current user id. */
public abstract int getCurrentUserId();
+ /** Returns the currently started user ids. */
+ public abstract int[] getStartedUserIds();
+
/** Returns true if the user is running. */
public abstract boolean isUserRunning(@UserIdInt int userId, int flags);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 62b5ec872320..9ed76c1c13d1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -932,6 +932,21 @@ public final class LoadedApk {
boolean registerAppInfoToArt = false;
if (mDefaultClassLoader == null) {
+ // Setup the dex reporter to notify package manager
+ // of any relevant dex loads. The idle maintenance job will use the information
+ // reported to optimize the loaded dex files.
+ // Note that we only need one global reporter per app.
+ // Make sure we do this before creating the main app classloader for the first time
+ // so that we can capture the complete application startup.
+ //
+ // We should not do this in a zygote context (where mActivityThread will be null),
+ // thus we'll guard against it.
+ // Also, the system server reporter (SystemServerDexLoadReporter) is already registered
+ // when system server starts, so we don't need to do it here again.
+ if (mActivityThread != null && !ActivityThread.isSystem()) {
+ BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
+ }
+
// Temporarily disable logging of disk reads on the Looper thread
// as this is early and necessary.
StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
@@ -1047,14 +1062,6 @@ public final class LoadedApk {
}
private void registerAppInfoToArt() {
- // Setup the dex reporter to notify package manager
- // of any relevant dex loads. The idle maintenance job will use the information
- // reported to optimize the loaded dex files.
- // Note that we only need one global reporter per app.
- // Make sure we do this before invoking app code for the first time so that we
- // can capture the complete application startup.
- BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
-
// Only set up profile support if the loaded apk has the same uid as the
// current process.
// Currently, we do not support profiling across different apps.
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index 8e3de616f07b..41272437c407 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -693,20 +693,42 @@ public final class CameraExtensionCharacteristics {
throw new IllegalArgumentException("Unsupported extension");
}
+ android.hardware.camera2.extension.Size sz =
+ new android.hardware.camera2.extension.Size();
+ sz.width = captureOutputSize.getWidth();
+ sz.height = captureOutputSize.getHeight();
if (areAdvancedExtensionsSupported()) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId);
- android.hardware.camera2.extension.Size sz =
- new android.hardware.camera2.extension.Size();
- sz.width = captureOutputSize.getWidth();
- sz.height = captureOutputSize.getHeight();
LatencyRange latencyRange = extender.getEstimatedCaptureLatencyRange(mCameraId,
sz, format);
if (latencyRange != null) {
return new Range(latencyRange.min, latencyRange.max);
}
- }
- } catch (RemoteException e) {
+ } else {
+ Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
+ initializeExtension(extension);
+ extenders.second.init(mCameraId, mChars.getNativeMetadata());
+ if ((format == ImageFormat.YUV_420_888) &&
+ (extenders.second.getCaptureProcessor() == null) ){
+ // Extensions that don't implement any capture processor are limited to
+ // JPEG only!
+ return null;
+ }
+ if ((format == ImageFormat.JPEG) &&
+ (extenders.second.getCaptureProcessor() != null)) {
+ // The framework will perform the additional encoding pass on the
+ // processed YUV_420 buffers. Latency in this case is very device
+ // specific and cannot be estimated accurately enough.
+ return null;
+ }
+
+ LatencyRange latencyRange = extenders.second.getEstimatedCaptureLatencyRange(sz);
+ if (latencyRange != null) {
+ return new Range(latencyRange.min, latencyRange.max);
+ }
+ }
+ } catch (RemoteException e) {
Log.e(TAG, "Failed to query the extension capture latency! Extension service does"
+ " not respond!");
} finally {
diff --git a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl
index c04e75ea6758..3ebf63793b79 100644
--- a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl
+++ b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl
@@ -19,6 +19,8 @@ import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.extension.CaptureStageImpl;
import android.hardware.camera2.extension.ICaptureProcessorImpl;
+import android.hardware.camera2.extension.LatencyRange;
+import android.hardware.camera2.extension.Size;
import android.hardware.camera2.extension.SizeList;
/** @hide */
@@ -36,4 +38,5 @@ interface IImageCaptureExtenderImpl
@nullable List<CaptureStageImpl> getCaptureStages();
int getMaxCaptureStage();
@nullable List<SizeList> getSupportedResolutions();
+ LatencyRange getEstimatedCaptureLatencyRange(in Size outputSize);
}
diff --git a/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl b/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl
index f365469eaecc..4c85966c10dc 100644
--- a/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl
+++ b/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl
@@ -21,5 +21,6 @@ import android.hardware.camera2.extension.ParcelImage;
/** @hide */
interface IImageProcessorImpl
{
- void onNextImageAvailable(in OutputConfigId outputConfigId, in ParcelImage image);
+ void onNextImageAvailable(in OutputConfigId outputConfigId, in ParcelImage image,
+ in String physicalCameraId);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index abc487db5bdb..5cf50a25de78 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -79,8 +79,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
private final HandlerThread mHandlerThread;
private final CameraExtensionSession.StateCallback mCallbacks;
private final IAdvancedExtenderImpl mAdvancedExtender;
- // maps camera outputs to extension output ids
- private final HashMap<Surface, Integer> mSurfaceIdMap = new HashMap<>();
+ // maps registered camera surfaces to extension output configs
+ private final HashMap<Surface, CameraOutputConfig> mCameraConfigMap = new HashMap<>();
// maps camera extension output ids to camera registered image readers
private final HashMap<Integer, ImageReader> mReaderMap = new HashMap<>();
private final RequestProcessor mRequestProcessor = new RequestProcessor();
@@ -226,7 +226,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
reader.getSurface());
break;
case CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER:
- // TBD
+ // Support for multi-resolution outputs to be added in future releases
default:
throw new IllegalArgumentException("Unsupported output config type: " +
output.type);
@@ -251,7 +251,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
}
}
outputList.add(outConfig);
- mSurfaceIdMap.put(outConfig.getSurface(), output.outputId.id);
+ mCameraConfigMap.put(outConfig.getSurface(), output);
}
SessionConfiguration sessionConfiguration = new SessionConfiguration(
@@ -629,7 +629,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
if (request.getTag() instanceof Integer) {
Integer requestId = (Integer) request.getTag();
mCallback.onCaptureBufferLost(requestId, frameNumber,
- mSurfaceIdMap.get(target));
+ mCameraConfigMap.get(target).outputId.id);
} else {
Log.e(TAG, "Invalid capture request tag!");
}
@@ -736,12 +736,14 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
private static final class ImageReaderHandler implements ImageReader.OnImageAvailableListener {
private final OutputConfigId mOutputConfigId;
private final IImageProcessorImpl mIImageProcessor;
+ private final String mPhysicalCameraId;
private ImageReaderHandler(int outputConfigId,
- IImageProcessorImpl iImageProcessor) {
+ IImageProcessorImpl iImageProcessor, String physicalCameraId) {
mOutputConfigId = new OutputConfigId();
mOutputConfigId.id = outputConfigId;
mIImageProcessor = iImageProcessor;
+ mPhysicalCameraId = physicalCameraId;
}
@Override
@@ -787,7 +789,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
parcelImage.crop = img.getCropRect();
try {
- mIImageProcessor.onNextImageAvailable(mOutputConfigId, parcelImage);
+ mIImageProcessor.onNextImageAvailable(mOutputConfigId, parcelImage,
+ mPhysicalCameraId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to propagate image buffer on output surface id: " +
mOutputConfigId + " extension service does not respond!");
@@ -804,8 +807,17 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
IImageProcessorImpl imageProcessor) {
synchronized (mInterfaceLock) {
if (mReaderMap.containsKey(outputConfigId.id)) {
- mReaderMap.get(outputConfigId.id).setOnImageAvailableListener(
- new ImageReaderHandler(outputConfigId.id, imageProcessor), mHandler);
+ ImageReader reader = mReaderMap.get(outputConfigId.id);
+ String physicalCameraId = null;
+ if (mCameraConfigMap.containsKey(reader.getSurface())) {
+ physicalCameraId =
+ mCameraConfigMap.get(reader.getSurface()).physicalCameraId;
+ reader.setOnImageAvailableListener(new ImageReaderHandler(outputConfigId.id,
+ imageProcessor, physicalCameraId), mHandler);
+ } else {
+ Log.e(TAG, "Camera output configuration for ImageReader with " +
+ " config Id " + outputConfigId.id + " not found!");
+ }
} else {
Log.e(TAG, "ImageReader with output config id: " + outputConfigId.id +
" not found!");
@@ -828,7 +840,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
for (Request request : requests) {
captureRequests.add(initializeCaptureRequest(mCameraDevice, request,
- mSurfaceIdMap));
+ mCameraConfigMap));
}
mCaptureSession.captureBurstRequests(captureRequests,
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
@@ -848,7 +860,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
synchronized (mInterfaceLock) {
try {
CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice,
- request, mSurfaceIdMap);
+ request, mCameraConfigMap);
CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
mCaptureSession.setSingleRepeatingRequest(repeatingRequest,
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
@@ -891,12 +903,13 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
}
private static CaptureRequest initializeCaptureRequest(CameraDevice cameraDevice,
- Request request, HashMap<Surface, Integer> surfaceIdMap) throws CameraAccessException {
+ Request request, HashMap<Surface, CameraOutputConfig> surfaceIdMap)
+ throws CameraAccessException {
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(request.templateId);
for (OutputConfigId configId : request.targetOutputConfigIds) {
boolean found = false;
- for (Map.Entry<Surface, Integer> entry : surfaceIdMap.entrySet()) {
- if (entry.getValue() == configId.id) {
+ for (Map.Entry<Surface, CameraOutputConfig> entry : surfaceIdMap.entrySet()) {
+ if (entry.getValue().outputId.id == configId.id) {
builder.addTarget(entry.getKey());
found = true;
break;
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index 5339f41ecdd6..4bcc4942d8a0 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -18,7 +18,6 @@ package android.hardware.camera2.impl;
import android.content.Context;
import android.graphics.ImageFormat;
-import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.hardware.camera2.CameraAccessException;
@@ -42,7 +41,6 @@ import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.ExtensionSessionConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
-import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.SurfaceUtils;
import android.media.Image;
import android.media.ImageReader;
@@ -68,7 +66,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
public final class CameraExtensionSessionImpl extends CameraExtensionSession {
private static final int PREVIEW_QUEUE_SIZE = 3;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 86380a294a3d..d42e0c367763 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1410,8 +1410,6 @@ public final class ViewRootImpl implements ViewParent,
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
attrs.getTitle().toString());
- addASurfaceTransactionCallback();
- mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
updateColorModeIfNeeded(attrs.getColorMode());
updateForceDarkMode();
if (mAttachInfo.mThreadedRenderer != null) {
@@ -1420,6 +1418,8 @@ public final class ViewRootImpl implements ViewParent,
if (mHardwareRendererObserver != null) {
mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
}
+ addASurfaceTransactionCallback();
+ mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
}
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d7010298adba..6533fc51accf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5658,6 +5658,8 @@
<!-- Allows query of any normal app on the device, regardless of manifest declarations.
<p>Protection level: normal -->
<permission android:name="android.permission.QUERY_ALL_PACKAGES"
+ android:label="@string/permlab_queryAllPackages"
+ android:description="@string/permdesc_queryAllPackages"
android:protectionLevel="normal" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 766ad167e5b3..bdeff89352ea 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3895,6 +3895,11 @@
<!-- Description of an application permission that lets it ask user to ignore battery optimizations for that app-->
<string name="permdesc_requestIgnoreBatteryOptimizations">Allows an app to ask for permission to ignore battery optimizations for that app.</string>
+ <!-- Title of an application permission that lets query all other packages. [CHAR LIMIT=NONE] -->
+ <string name="permlab_queryAllPackages">query all packages</string>
+ <!-- Description of an application permission that lets it query all other packages. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_queryAllPackages">Allows an app to see all installed packages.</string>
+
<!-- Shown in the tutorial for tap twice for zoom control. -->
<string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 0d8715bfaef2..fe80b5845bf5 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -331,18 +331,18 @@ public class RippleDrawable extends LayerDrawable {
private void setRippleActive(boolean active) {
if (mRippleActive != active) {
mRippleActive = active;
- }
- if (mState.mRippleStyle == STYLE_SOLID) {
- if (active) {
- tryRippleEnter();
- } else {
- tryRippleExit();
- }
- } else {
- if (active) {
- startPatternedAnimation();
+ if (mState.mRippleStyle == STYLE_SOLID) {
+ if (active) {
+ tryRippleEnter();
+ } else {
+ tryRippleExit();
+ }
} else {
- exitPatternedAnimation();
+ if (active) {
+ startPatternedAnimation();
+ } else {
+ exitPatternedAnimation();
+ }
}
}
}
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index ee7b26058952..d86d9ee56f4c 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -204,10 +204,9 @@ static sk_sp<SkData> makeSkDataCached(const std::string& path, bool hasVerity) {
return entry;
}
-static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia(
- minikin::BufferReader* reader) {
- const void* buffer = reader->data();
- size_t pos = reader->pos();
+static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader);
+
+static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader) {
// Advance reader's position.
reader->skipString(); // fontPath
reader->skip<int>(); // fontIndex
@@ -217,60 +216,63 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki
reader->skip<uint32_t>(); // expectedFontRevision
reader->skipString(); // expectedPostScriptName
}
- return [buffer, pos]() -> std::shared_ptr<minikin::MinikinFont> {
- minikin::BufferReader fontReader(buffer, pos);
- std::string_view fontPath = fontReader.readString();
- std::string path(fontPath.data(), fontPath.size());
- ATRACE_FORMAT("Loading font %s", path.c_str());
- int fontIndex = fontReader.read<int>();
- const minikin::FontVariation* axesPtr;
- uint32_t axesCount;
- std::tie(axesPtr, axesCount) = fontReader.readArray<minikin::FontVariation>();
- bool hasVerity = static_cast<bool>(fontReader.read<int8_t>());
- uint32_t expectedFontRevision;
- std::string_view expectedPostScriptName;
- if (hasVerity) {
- expectedFontRevision = fontReader.read<uint32_t>();
- expectedPostScriptName = fontReader.readString();
- }
- sk_sp<SkData> data = makeSkDataCached(path, hasVerity);
- if (data.get() == nullptr) {
- // This may happen if:
- // 1. When the process failed to open the file (e.g. invalid path or permission).
- // 2. When the process failed to map the file (e.g. hitting max_map_count limit).
- ALOGE("Failed to make SkData from file name: %s", path.c_str());
+ return &loadMinikinFontSkia;
+}
+
+static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader reader) {
+ std::string_view fontPath = reader.readString();
+ std::string path(fontPath.data(), fontPath.size());
+ ATRACE_FORMAT("Loading font %s", path.c_str());
+ int fontIndex = reader.read<int>();
+ const minikin::FontVariation* axesPtr;
+ uint32_t axesCount;
+ std::tie(axesPtr, axesCount) = reader.readArray<minikin::FontVariation>();
+ bool hasVerity = static_cast<bool>(reader.read<int8_t>());
+ uint32_t expectedFontRevision;
+ std::string_view expectedPostScriptName;
+ if (hasVerity) {
+ expectedFontRevision = reader.read<uint32_t>();
+ expectedPostScriptName = reader.readString();
+ }
+ sk_sp<SkData> data = makeSkDataCached(path, hasVerity);
+ if (data.get() == nullptr) {
+ // This may happen if:
+ // 1. When the process failed to open the file (e.g. invalid path or permission).
+ // 2. When the process failed to map the file (e.g. hitting max_map_count limit).
+ ALOGE("Failed to make SkData from file name: %s", path.c_str());
+ return nullptr;
+ }
+ const void* fontPtr = data->data();
+ size_t fontSize = data->size();
+ if (hasVerity) {
+ // Verify font metadata if verity is enabled.
+ minikin::FontFileParser parser(fontPtr, fontSize, fontIndex);
+ std::optional<uint32_t> revision = parser.getFontRevision();
+ if (!revision.has_value() || revision.value() != expectedFontRevision) {
+ LOG_ALWAYS_FATAL("Wrong font revision: %s", path.c_str());
return nullptr;
}
- const void* fontPtr = data->data();
- size_t fontSize = data->size();
- if (hasVerity) {
- // Verify font metadata if verity is enabled.
- minikin::FontFileParser parser(fontPtr, fontSize, fontIndex);
- std::optional<uint32_t> revision = parser.getFontRevision();
- if (!revision.has_value() || revision.value() != expectedFontRevision) {
- LOG_ALWAYS_FATAL("Wrong font revision: %s", path.c_str());
- return nullptr;
- }
- std::optional<std::string> psName = parser.getPostScriptName();
- if (!psName.has_value() || psName.value() != expectedPostScriptName) {
- LOG_ALWAYS_FATAL("Wrong PostScript name: %s", path.c_str());
- return nullptr;
- }
- }
- std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount);
- std::shared_ptr<minikin::MinikinFont> minikinFont =
- fonts::createMinikinFontSkia(std::move(data), fontPath, fontPtr, fontSize,
- fontIndex, axes);
- if (minikinFont == nullptr) {
- ALOGE("Failed to create MinikinFontSkia: %s", path.c_str());
+ std::optional<std::string> psName = parser.getPostScriptName();
+ if (!psName.has_value() || psName.value() != expectedPostScriptName) {
+ LOG_ALWAYS_FATAL("Wrong PostScript name: %s", path.c_str());
return nullptr;
}
- return minikinFont;
- };
+ }
+ std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount);
+ std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(
+ std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes);
+ if (minikinFont == nullptr) {
+ ALOGE("Failed to create MinikinFontSkia: %s", path.c_str());
+ return nullptr;
+ }
+ return minikinFont;
}
static void writeMinikinFontSkia(minikin::BufferWriter* writer,
const minikin::MinikinFont* typeface) {
+ // When you change the format of font metadata, please update code to parse
+ // typefaceMetadataReader() in
+ // frameworks/base/libs/hwui/jni/fonts/Font.cpp too.
const std::string& path = typeface->GetFontPath();
writer->writeString(path);
writer->write<int>(typeface->GetFontIndex());
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index bd3b7c93466c..09be630dc741 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -192,7 +192,7 @@ static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong
// Critical Native
static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- return reinterpret_cast<jlong>(font->font->typeface().get());
+ return reinterpret_cast<jlong>(font->font.get());
}
// Critical Native
@@ -224,12 +224,21 @@ static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) {
// Fast Native
static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- const std::string& path = minikinFont->GetFontPath();
- if (path.empty()) {
- return nullptr;
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ if (reader.data() != nullptr) {
+ std::string path = std::string(reader.readString());
+ if (path.empty()) {
+ return nullptr;
+ }
+ return env->NewStringUTF(path.c_str());
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ const std::string& path = minikinFont->GetFontPath();
+ if (path.empty()) {
+ return nullptr;
+ }
+ return env->NewStringUTF(path.c_str());
}
- return env->NewStringUTF(path.c_str());
}
// Fast Native
@@ -257,22 +266,43 @@ static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
// Critical Native
static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- return minikinFont->GetFontIndex();
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ if (reader.data() != nullptr) {
+ reader.skipString(); // fontPath
+ return reader.read<int>();
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ return minikinFont->GetFontIndex();
+ }
}
// Critical Native
static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- return minikinFont->GetAxes().size();
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ if (reader.data() != nullptr) {
+ reader.skipString(); // fontPath
+ reader.skip<int>(); // fontIndex
+ return reader.readArray<minikin::FontVariation>().second;
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ return minikinFont->GetAxes().size();
+ }
}
// Critical Native
static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- minikin::FontVariation var = minikinFont->GetAxes().at(index);
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ minikin::FontVariation var;
+ if (reader.data() != nullptr) {
+ reader.skipString(); // fontPath
+ reader.skip<int>(); // fontIndex
+ var = reader.readArray<minikin::FontVariation>().first[index];
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ var = minikinFont->GetAxes().at(index);
+ }
uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
}
diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml
index e5e8fe6ed5dc..687830d5c7b3 100644
--- a/packages/SystemUI/res/layout/udfps_view.xml
+++ b/packages/SystemUI/res/layout/udfps_view.xml
@@ -20,7 +20,7 @@
android:id="@+id/udfps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- systemui:sensorTouchAreaCoefficient="0.5"
+ systemui:sensorTouchAreaCoefficient="0.75"
android:contentDescription="@string/accessibility_fingerprint_label">
<ViewStub
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index d1cb6ec7a072..c4f78e7782a2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -376,6 +376,17 @@ public class AuthContainerView extends LinearLayout
addView(mFrameLayout);
+ // init view before showing
+ if (mBiometricView != null) {
+ mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
+ mBiometricView.setPanelController(mPanelController);
+ mBiometricView.setPromptInfo(mConfig.mPromptInfo);
+ mBiometricView.setCallback(mBiometricCallback);
+ mBiometricView.setBackgroundView(mBackgroundView);
+ mBiometricView.setUserId(mConfig.mUserId);
+ mBiometricView.setEffectiveUserId(mEffectiveUserId);
+ }
+
// TODO: De-dupe the logic with AuthCredentialPasswordView
setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
@@ -404,13 +415,6 @@ public class AuthContainerView extends LinearLayout
}
private void addBiometricView() {
- mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
- mBiometricView.setPanelController(mPanelController);
- mBiometricView.setPromptInfo(mConfig.mPromptInfo);
- mBiometricView.setCallback(mBiometricCallback);
- mBiometricView.setBackgroundView(mBackgroundView);
- mBiometricView.setUserId(mConfig.mUserId);
- mBiometricView.setEffectiveUserId(mEffectiveUserId);
mBiometricScrollView.addView(mBiometricView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 980bb12d390c..00888dfe48d3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -355,7 +355,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@Override
public void onBouncerVisibilityChanged() {
- mIsBouncerVisible = mKeyguardViewManager.bouncerIsOrWillBeShowing();
+ mIsBouncerVisible = mKeyguardViewManager.isBouncerShowing();
if (!mIsBouncerVisible) {
mInputBouncerHiddenAmount = 1f;
} else if (mKeyguardViewManager.isBouncerShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index c45eb3558948..ff95604088ed 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -307,7 +307,7 @@ public class DozeTriggers implements DozeMachine.Part {
// Since the gesture won't be received by the UDFPS view, manually inject an
// event.
mAuthController.onAodInterrupt((int) screenX, (int) screenY,
- rawValues[2] /* major */, rawValues[3] /* minor */);
+ rawValues[3] /* major */, rawValues[4] /* minor */);
} else {
mDozeHost.extendPulse(pulseReason);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 032f9c4e7581..0d9749e05262 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -104,7 +104,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private static final int MAX_NUM_LOGGED_GESTURES = 10;
// Temporary log until b/176302696 is resolved
- static final boolean DEBUG_MISSING_GESTURE = true;
+ static final boolean DEBUG_MISSING_GESTURE = false;
static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
@@ -147,6 +147,16 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
mPackageName = "_UNKNOWN";
}
}
+
+ @Override
+ public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
+ mIsInPipMode = true;
+ }
+
+ @Override
+ public void onActivityUnpinned() {
+ mIsInPipMode = false;
+ }
};
private DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
@@ -220,6 +230,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private boolean mIsNavBarShownTransiently;
private boolean mIsBackGestureAllowed;
private boolean mGestureBlockingActivityRunning;
+ private boolean mIsInPipMode;
private InputMonitor mInputMonitor;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -636,7 +647,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
// If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
// gesture
- if (mPipExcludedBounds.contains(x, y) || mNavBarOverlayExcludedBounds.contains(x, y)) {
+ final boolean isInsidePip = mIsInPipMode && mPipExcludedBounds.contains(x, y);
+ if (isInsidePip || mNavBarOverlayExcludedBounds.contains(x, y)) {
return false;
}
@@ -898,6 +910,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
pw.println(" mInRejectedExclusion" + mInRejectedExclusion);
pw.println(" mExcludeRegion=" + mExcludeRegion);
pw.println(" mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
+ pw.println(" mIsInPipMode=" + mIsInPipMode);
pw.println(" mPipExcludedBounds=" + mPipExcludedBounds);
pw.println(" mNavBarOverlayExcludedBounds=" + mNavBarOverlayExcludedBounds);
pw.println(" mEdgeWidthLeft=" + mEdgeWidthLeft);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 1a828e45dc38..cbdcad5cf385 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,9 +16,7 @@
package com.android.systemui.qs;
-import android.content.Intent;
import android.os.Bundle;
-import android.provider.AlarmClock;
import android.view.View;
import android.view.View.OnClickListener;
@@ -113,10 +111,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private View.OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
- if (v == mClockView) {
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- AlarmClock.ACTION_SHOW_ALARMS), 0);
- } else if (v == mPrivacyChip) {
+ if (v == mPrivacyChip) {
// If the privacy chip is visible, it means there were some indicators
mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
mPrivacyDialogController.showDialog(getContext());
@@ -167,7 +162,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
@Override
protected void onViewAttached() {
- mClockView.setOnClickListener(mOnClickListener);
mPrivacyChip.setOnClickListener(mOnClickListener);
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
@@ -188,7 +182,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
@Override
protected void onViewDetached() {
- mClockView.setOnClickListener(null);
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
mPrivacyChip.setOnClickListener(null);
mStatusBarIconController.removeIconGroup(mIconManager);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index f4c15fbf90b8..cb0c411b2753 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -560,8 +560,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
mSmartspaceTransitionController.createExternalInterface().asBinder());
try {
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.onInitialize: curUser="
- + mCurrentBoundedUserId);
mOverviewProxy.onInitialize(params);
} catch (RemoteException e) {
mCurrentBoundedUserId = -1;
@@ -646,7 +644,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
// Listen for nav bar mode changes
mNavBarMode = navModeController.addListener(this);
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService: mode=" + mNavBarMode);
// Listen for launcher package changes
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
@@ -807,7 +804,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
mOverviewServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
UserHandle.of(getCurrentUserId()));
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.connect: bound=" + mBound);
} catch (SecurityException e) {
Log.e(TAG_OPS, "Unable to bind because of security error", e);
}
@@ -860,9 +856,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
private void disconnectFromLauncherService() {
if (mBound) {
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.disconnect: curUser="
- + mCurrentBoundedUserId);
-
// Always unbind the service (ie. if called through onNullBinding or onBindingDied)
mContext.unbindService(mOverviewServiceConnection);
mBound = false;
@@ -993,14 +986,11 @@ public class OverviewProxyService extends CurrentUserTracker implements
final int currentUser = ActivityManagerWrapper.getInstance().getCurrentUserId();
mIsEnabled = mContext.getPackageManager().resolveServiceAsUser(mQuickStepIntent,
MATCH_SYSTEM_ONLY, currentUser) != null;
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.updateEnabledState: curUser="
- + currentUser + " enabled=" + mIsEnabled);
}
@Override
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.onNavModeChanged: mode=" + mode);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1331829201b8..7a1e5cf1770b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -642,7 +642,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
return;
}
- if (mState == ScrimState.UNLOCKED) {
+ if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) {
// Darken scrim as you pull down the shade when unlocked, unless the shade is expanding
// because we're doing the screen off animation.
if (!mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
@@ -657,12 +657,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
mInFrontAlpha = 0;
}
- } else if (mState == ScrimState.BUBBLE_EXPANDED) {
- // Darken scrim as you pull down the shade when unlocked
- float behindFraction = getInterpolatedFraction();
- behindFraction = (float) Math.pow(behindFraction, 0.8f);
- mBehindAlpha = behindFraction * mDefaultScrimAlpha;
- mInFrontAlpha = 0;
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
|| mState == ScrimState.PULSING) {
Pair<Integer, Float> result = calculateBackStateForState(mState);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 4a9d66c16003..c0b45c6d5c96 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -236,13 +236,14 @@ public class DozeTriggersTest extends SysuiTestCase {
public void testOnSensor_Fingerprint() {
final int screenX = 100;
final int screenY = 100;
+ final float misc = -1;
final float minor = 2f;
final float major = 3f;
final int reason = DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
- float[] rawValues = new float[]{screenX, screenY, minor, major};
+ float[] rawValues = new float[]{screenX, screenY, misc, major, minor};
mTriggers.onSensor(reason, screenX, screenY, rawValues);
verify(mHost).extendPulse(reason);
- verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(minor), eq(major));
+ verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(major), eq(minor));
}
private void waitForSensorManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 3c1b36e41d89..7ac6f8212a61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -127,6 +127,11 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
}
@Test
+ fun testClockNotClickable() {
+ assertThat(clock.isClickable).isFalse()
+ }
+
+ @Test
fun testIgnoredSlotsOnAttached_noIndicators() {
setPrivacyController(micCamera = false, location = false)
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java
index d44a4173fc12..7b9ca2ddc345 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java
@@ -119,20 +119,32 @@ public class CameraExtensionsProxyService extends Service {
private static final String CAMERA_EXTENSION_VERSION_NAME =
"androidx.camera.extensions.impl.ExtensionVersionImpl";
private static final String LATEST_VERSION = "1.2.0";
- private static final String LEGACY_VERSION_PREFIX = "1.1";
+ private static final String NON_INIT_VERSION_PREFIX = "1.0";
private static final String ADVANCED_VERSION_PREFIX = "1.2";
private static final String[] SUPPORTED_VERSION_PREFIXES = {ADVANCED_VERSION_PREFIX,
- LEGACY_VERSION_PREFIX, "1.0."};
+ "1.1", NON_INIT_VERSION_PREFIX};
private static final boolean EXTENSIONS_PRESENT = checkForExtensions();
private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ?
(new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null;
- private static final boolean LEGACY_VERSION_SUPPORTED =
- EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(LEGACY_VERSION_PREFIX);
- private static final boolean ADVANCED_VERSION_SUPPORTED =
- EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX);
+ private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI();
+ private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT &&
+ (!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX));
private HashMap<String, CameraCharacteristics> mCharacteristicsHashMap = new HashMap<>();
+ private static boolean checkForAdvancedAPI() {
+ if (EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
+ try {
+ return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented();
+ } catch (NoSuchMethodError e) {
+ // This could happen in case device specific extension implementations are using an
+ // older extension API but incorrectly set the extension version.
+ }
+ }
+
+ return false;
+ }
+
private static boolean checkForExtensions() {
try {
Class.forName(CAMERA_EXTENSION_VERSION_NAME);
@@ -265,7 +277,7 @@ public class CameraExtensionsProxyService extends Service {
public long registerClient(Context ctx) {
synchronized (mLock) {
- if (LEGACY_VERSION_SUPPORTED) {
+ if (INIT_API_SUPPORTED) {
if (mActiveClients.isEmpty()) {
InitializerFuture status = new InitializerFuture();
InitializerImpl.init(EXTENSIONS_VERSION, ctx, new InitializeHandler(status),
@@ -299,7 +311,7 @@ public class CameraExtensionsProxyService extends Service {
public void unregisterClient(long clientId) {
synchronized (mLock) {
if (mActiveClients.remove(clientId) && mActiveClients.isEmpty() &&
- LEGACY_VERSION_SUPPORTED) {
+ INIT_API_SUPPORTED) {
InitializerFuture status = new InitializerFuture();
InitializerImpl.deinit(new ReleaseHandler(status),
new HandlerExecutor(mHandler));
@@ -528,7 +540,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public boolean advancedExtensionsSupported() {
- return ADVANCED_VERSION_SUPPORTED;
+ return ADVANCED_API_SUPPORTED;
}
@Override
@@ -819,10 +831,11 @@ public class CameraExtensionsProxyService extends Service {
}
@Override
- public void onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img) {
+ public void onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img,
+ String physicalCameraId) {
if (mImageProcessor != null) {
mImageProcessor.onNextImageAvailable(outputConfigId.id, img.timestamp,
- new ImageReferenceImpl(img));
+ new ImageReferenceImpl(img), physicalCameraId);
}
}
}
@@ -1072,9 +1085,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public void init(String cameraId, CameraMetadataNative chars) {
- if (LEGACY_VERSION_SUPPORTED) {
- mPreviewExtender.init(cameraId, new CameraCharacteristics(chars));
- }
+ mPreviewExtender.init(cameraId, new CameraCharacteristics(chars));
}
@Override
@@ -1136,7 +1147,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public List<SizeList> getSupportedResolutions() {
- if (LEGACY_VERSION_SUPPORTED) {
+ if (INIT_API_SUPPORTED) {
List<Pair<Integer, android.util.Size[]>> sizes =
mPreviewExtender.getSupportedResolutions();
if ((sizes != null) && !sizes.isEmpty()) {
@@ -1182,9 +1193,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public void init(String cameraId, CameraMetadataNative chars) {
- if (LEGACY_VERSION_SUPPORTED) {
- mImageExtender.init(cameraId, new CameraCharacteristics(chars));
- }
+ mImageExtender.init(cameraId, new CameraCharacteristics(chars));
}
@Override
@@ -1228,7 +1237,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public List<SizeList> getSupportedResolutions() {
- if (LEGACY_VERSION_SUPPORTED) {
+ if (INIT_API_SUPPORTED) {
List<Pair<Integer, android.util.Size[]>> sizes =
mImageExtender.getSupportedResolutions();
if ((sizes != null) && !sizes.isEmpty()) {
@@ -1238,6 +1247,23 @@ public class CameraExtensionsProxyService extends Service {
return null;
}
+
+ @Override
+ public LatencyRange getEstimatedCaptureLatencyRange(
+ android.hardware.camera2.extension.Size outputSize) {
+ if (EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
+ Size sz = new Size(outputSize.width, outputSize.height);
+ Range<Long> latencyRange = mImageExtender.getEstimatedCaptureLatencyRange(sz);
+ if (latencyRange != null) {
+ LatencyRange ret = new LatencyRange();
+ ret.min = latencyRange.getLower();
+ ret.max = latencyRange.getUpper();
+ return ret;
+ }
+ }
+
+ return null;
+ }
}
private class CaptureProcessorImplStub extends ICaptureProcessorImpl.Stub {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c841fa3b057c..231d4b1da58a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14309,7 +14309,7 @@ public class ActivityManagerService extends IActivityManager.Stub
private boolean checkExcessivePowerUsageLPr(final long uptimeSince, boolean doCpuKills,
final long cputimeUsed, final String processName, final String description,
final int cpuLimit, final ProcessRecord app) {
- if (DEBUG_POWER) {
+ if (DEBUG_POWER && (uptimeSince > 0)) {
StringBuilder sb = new StringBuilder(128);
sb.append("CPU for ");
sb.append(description);
@@ -15349,6 +15349,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public int[] getStartedUserIds() {
+ return mUserController.getStartedUserArray();
+ }
+
+ @Override
public void setPendingIntentAllowBgActivityStarts(IIntentSender target,
IBinder allowlistToken, int flags) {
if (!(target instanceof PendingIntentRecord)) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3bfd62b60c89..8ebc987a59f4 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -4289,8 +4289,8 @@ public final class ProcessList {
if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
long lastCpuTime = r.mProfile.mLastCpuTime.get();
- if (lastCpuTime != 0) {
- long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+ long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+ if (lastCpuTime != 0 && uptimeSince > 0) {
long timeUsed = r.mProfile.mCurCpuTime.get() - lastCpuTime;
long cpuTimeToken = proto.start(ProcessOomProto.Detail.SERVICE_RUN_TIME);
proto.write(ProcessOomProto.Detail.CpuRunTime.OVER_MS, uptimeSince);
@@ -4427,7 +4427,7 @@ public final class ProcessList {
if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
long lastCpuTime = r.mProfile.mLastCpuTime.get();
- if (lastCpuTime != 0) {
+ if (lastCpuTime != 0 && uptimeSince > 0) {
long timeUsed = r.mProfile.mCurCpuTime.get() - lastCpuTime;
pw.print(prefix);
pw.print(" ");
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 6f73985fbcd4..5cd330a5753c 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -27,6 +27,8 @@ import static android.Manifest.permission.USE_FINGERPRINT;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricManager.Authenticators;
import android.annotation.NonNull;
@@ -76,7 +78,6 @@ import java.util.List;
*/
public class AuthService extends SystemService {
private static final String TAG = "AuthService";
- private static final boolean DEBUG = false;
private static final String SETTING_HIDL_DISABLED =
"com.android.server.biometrics.AuthService.hidlDisabled";
private static final int DEFAULT_HIDL_DISABLED = 0;
@@ -208,7 +209,6 @@ public class AuthService extends SystemService {
public void authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo)
throws RemoteException {
-
// Only allow internal clients to authenticate with a different userId.
final int callingUserId = UserHandle.getCallingUserId();
final int callingUid = Binder.getCallingUid();
@@ -222,17 +222,18 @@ public class AuthService extends SystemService {
}
if (!checkAppOps(callingUid, opPackageName, "authenticate()")) {
- Slog.e(TAG, "Denied by app ops: " + opPackageName);
+ authenticateFastFail("Denied by app ops: " + opPackageName, receiver);
return;
}
- if (!Utils.isForeground(callingUid, callingPid)) {
- Slog.e(TAG, "Caller is not foreground: " + opPackageName);
+ if (token == null || receiver == null || opPackageName == null || promptInfo == null) {
+ authenticateFastFail(
+ "Unable to authenticate, one or more null arguments", receiver);
return;
}
- if (token == null || receiver == null || opPackageName == null || promptInfo == null) {
- Slog.e(TAG, "Unable to authenticate, one or more null arguments");
+ if (!Utils.isForeground(callingUid, callingPid)) {
+ authenticateFastFail("Caller is not foreground: " + opPackageName, receiver);
return;
}
@@ -257,6 +258,17 @@ public class AuthService extends SystemService {
}
}
+ private void authenticateFastFail(String message, IBiometricServiceReceiver receiver) {
+ // notify caller in cases where authentication is aborted before calling into
+ // IBiometricService without raising an exception
+ Slog.e(TAG, message);
+ try {
+ receiver.onError(TYPE_NONE, BIOMETRIC_ERROR_CANCELED, 0 /*vendorCode */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "authenticateFastFail failed to notify caller", e);
+ }
+ }
+
@Override
public void cancelAuthentication(IBinder token, String opPackageName)
throws RemoteException {
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index ef02a472969b..8f364890aa06 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -679,7 +679,8 @@ public final class AuthSession implements IBinder.DeathRecipient {
FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
latency,
mDebugEnabled,
- -1 /* sensorId */);
+ -1 /* sensorId */,
+ -1f /* ambientLightLux */);
} else {
final long latency = System.currentTimeMillis() - mStartTimeMs;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 99f4e2cb280c..f51b1c2a4f0c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -69,6 +69,31 @@ public abstract class BaseClientMonitor extends LoggableMonitor
}
}
+ /** Holder for wrapping multiple handlers into a single Callback. */
+ protected static class CompositeCallback implements Callback {
+ @NonNull
+ private final Callback[] mCallbacks;
+
+ public CompositeCallback(@NonNull Callback... callbacks) {
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public final void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].onClientStarted(clientMonitor);
+ }
+ }
+
+ @Override
+ public final void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
+ for (int i = mCallbacks.length - 1; i >= 0; i--) {
+ mCallbacks[i].onClientFinished(clientMonitor, success);
+ }
+ }
+ }
+
private final int mSequentialId;
@NonNull private final Context mContext;
private final int mTargetUserId;
@@ -125,7 +150,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
int statsClient) {
- super(statsModality, statsAction, statsClient);
+ super(context, statsModality, statsAction, statsClient);
mSequentialId = sCount++;
mContext = context;
mToken = token;
@@ -153,10 +178,19 @@ public abstract class BaseClientMonitor extends LoggableMonitor
* @param callback invoked when the operation is complete (succeeds, fails, etc)
*/
public void start(@NonNull Callback callback) {
- mCallback = callback;
+ mCallback = wrapCallbackForStart(callback);
mCallback.onClientStarted(this);
}
+ /**
+ * Called during start to provide subclasses a hook for decorating the callback.
+ *
+ * Returns the original callback unless overridden.
+ */
+ @NonNull
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return callback;
+ }
public boolean isAlreadyDone() {
return mAlreadyDone;
diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
index 4da644d23dec..c8867ea2df1c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
@@ -16,7 +16,13 @@
package com.android.server.biometrics.sensors;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.face.FaceManager;
@@ -37,26 +43,47 @@ public abstract class LoggableMonitor {
final int mStatsModality;
private final int mStatsAction;
private final int mStatsClient;
+ @NonNull private final SensorManager mSensorManager;
private long mFirstAcquireTimeMs;
+ private boolean mLightSensorEnabled = false;
private boolean mShouldLogMetrics = true;
- /**
- * Only valid for AuthenticationClient.
- * @return true if the client is authenticating for a crypto operation.
- */
- protected boolean isCryptoOperation() {
- return false;
- }
+ // report only the most recent value
+ // consider com.android.server.display.utils.AmbientFilter or similar if need arises
+ private volatile float mLastAmbientLux = 0;
+
+ private final SensorEventListener mLightSensorListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ mLastAmbientLux = event.values[0];
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // Not used.
+ }
+ };
/**
+ * @param context system_server context
* @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
*/
- public LoggableMonitor(int statsModality, int statsAction, int statsClient) {
+ public LoggableMonitor(@NonNull Context context, int statsModality, int statsAction,
+ int statsClient) {
mStatsModality = statsModality;
mStatsAction = statsAction;
mStatsClient = statsClient;
+ mSensorManager = context.getSystemService(SensorManager.class);
+ }
+
+ /**
+ * Only valid for AuthenticationClient.
+ * @return true if the client is authenticating for a crypto operation.
+ */
+ protected boolean isCryptoOperation() {
+ return false;
}
protected void setShouldLog(boolean shouldLog) {
@@ -131,7 +158,6 @@ public abstract class LoggableMonitor {
}
protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
-
if (!mShouldLogMetrics) {
return;
}
@@ -199,7 +225,8 @@ public abstract class LoggableMonitor {
+ ", Client: " + mStatsClient
+ ", RequireConfirmation: " + requireConfirmation
+ ", State: " + authState
- + ", Latency: " + latency);
+ + ", Latency: " + latency
+ + ", Lux: " + mLastAmbientLux);
} else {
Slog.v(TAG, "Authentication latency: " + latency);
}
@@ -217,7 +244,8 @@ public abstract class LoggableMonitor {
authState,
sanitizeLatency(latency),
Utils.isDebugEnabled(context, targetUserId),
- -1 /* sensorId */);
+ -1 /* sensorId */,
+ mLastAmbientLux /* ambientLightLux */);
}
protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
@@ -230,6 +258,7 @@ public abstract class LoggableMonitor {
+ ", User: " + targetUserId
+ ", Client: " + mStatsClient
+ ", Latency: " + latency
+ + ", Lux: " + mLastAmbientLux
+ ", Success: " + enrollSuccessful);
} else {
Slog.v(TAG, "Enroll latency: " + latency);
@@ -244,7 +273,8 @@ public abstract class LoggableMonitor {
targetUserId,
sanitizeLatency(latency),
enrollSuccessful,
- -1 /* sensorId */);
+ -1, /* sensorId */
+ mLastAmbientLux /* ambientLightLux */);
}
private long sanitizeLatency(long latency) {
@@ -255,4 +285,46 @@ public abstract class LoggableMonitor {
return latency;
}
+ /** Get a callback to start/stop ALS capture when client runs. */
+ @NonNull
+ protected BaseClientMonitor.Callback createALSCallback() {
+ return new BaseClientMonitor.Callback() {
+ @Override
+ public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+ setLightSensorLoggingEnabled(getAmbientLightSensor(mSensorManager));
+ }
+
+ @Override
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
+ setLightSensorLoggingEnabled(null);
+ }
+ };
+ }
+
+ /** The sensor to use for ALS logging. */
+ @Nullable
+ protected Sensor getAmbientLightSensor(@NonNull SensorManager sensorManager) {
+ return mShouldLogMetrics ? sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) : null;
+ }
+
+ private void setLightSensorLoggingEnabled(@Nullable Sensor lightSensor) {
+ if (DEBUG) {
+ Slog.v(TAG, "capturing ambient light using: "
+ + (lightSensor != null ? lightSensor : "[disabled]"));
+ }
+
+ if (lightSensor != null) {
+ if (!mLightSensorEnabled) {
+ mLightSensorEnabled = true;
+ mLastAmbientLux = 0;
+ mSensorManager.registerListener(mLightSensorListener, lightSensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ } else {
+ mLightSensorEnabled = false;
+ mLastAmbientLux = 0;
+ mSensorManager.unregisterListener(mLightSensorListener);
+ }
+ }
}
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 2ab1285ba8a7..2adf5f98cee5 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
@@ -99,6 +99,12 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
"face_custom_success_error", 0) == 1;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected void startHalOperation() {
try {
@@ -229,7 +235,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
}
- @Override public void onLockoutTimed(long durationMillis) {
+ @Override
+ public void onLockoutTimed(long durationMillis) {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT;
@@ -242,7 +249,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
}
- @Override public void onLockoutPermanent() {
+ @Override
+ public void onLockoutPermanent() {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index f97414780247..ff68aa87dbbb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -95,6 +95,12 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
ReEnrollNotificationUtils.cancelNotification(getContext());
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void destroy() {
try {
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 c4bdb320ddef..01dd18fb5cf0 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
@@ -88,6 +88,12 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
"face_custom_success_error", 0) == 1;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected void startHalOperation() {
try {
@@ -186,7 +192,6 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
@Override
public void onAcquired(int acquireInfo, int vendorCode) {
-
mLastAcquire = acquireInfo;
if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index fc1200a4b42a..d3bd18b6f704 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -68,6 +68,12 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
.getIntArray(R.array.config_face_acquire_vendor_enroll_ignorelist);
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected boolean hasReachedEnrollmentLimit() {
final int limit = getContext().getResources().getInteger(
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 a5326b352264..3c9d802cb4b1 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
@@ -70,6 +70,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
mUdfpsOverlayController = udfpsOverlayController;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index edd30bc6b333..11849661693b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -79,6 +79,12 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
}
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
super.onEnrollResult(identifier, remaining);
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 24ed85c42e4e..45e35e34b62b 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
@@ -69,6 +69,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
mUdfpsOverlayController = udfpsOverlayController;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index 4f3e930c4e88..a28a3f6bd5c3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -72,6 +72,12 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
}
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected boolean hasReachedEnrollmentLimit() {
final int limit = getContext().getResources().getInteger(
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java b/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java
index 5ec85e661b98..6931baa948a1 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java
@@ -32,16 +32,18 @@ public class ContextHubShellCommand extends ShellCommand {
// Internal service impl -- must perform security checks before touching.
private final ContextHubService mInternal;
+ private final Context mContext;
public ContextHubShellCommand(Context context, ContextHubService service) {
mInternal = service;
-
- context.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_CONTEXT_HUB, "ContextHubShellCommand");
+ mContext = context;
}
@Override
public int onCommand(String cmd) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_CONTEXT_HUB, "ContextHubShellCommand");
+
if ("deny".equals(cmd)) {
return runDisableAuth();
}
diff --git a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
index 2cc2ebf616c5..2defe73addc6 100644
--- a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
+++ b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.media.metrics;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.media.metrics.IMediaMetricsManager;
import android.media.metrics.NetworkEvent;
import android.media.metrics.PlaybackErrorEvent;
@@ -24,19 +25,29 @@ import android.media.metrics.PlaybackMetrics;
import android.media.metrics.PlaybackStateEvent;
import android.media.metrics.TrackChangeEvent;
import android.os.Binder;
+import android.provider.DeviceConfig;
import android.util.Base64;
+import android.util.Slog;
import android.util.StatsEvent;
import android.util.StatsLog;
import com.android.server.SystemService;
import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
/**
* System service manages media metrics.
*/
public final class MediaMetricsManagerService extends SystemService {
+ private static final String TAG = "MediaMetricsManagerService";
+ // TODO: update these constants when finalized
+ private static final String MEDIA_METRICS_MODE = "media_metrics_mode";
+ private static final int MEDIA_METRICS_MODE_OFF = 0;
+ private static final int MEDIA_METRICS_MODE_ON = 1;
private final SecureRandom mSecureRandom;
+ private List<String> mBlockList = new ArrayList<>();
/**
* Initializes the playback metrics manager service.
@@ -56,6 +67,9 @@ public final class MediaMetricsManagerService extends SystemService {
private final class BinderService extends IMediaMetricsManager.Stub {
@Override
public void reportPlaybackMetrics(String sessionId, PlaybackMetrics metrics, int userId) {
+ if (!shouldWriteStats()) {
+ return;
+ }
StatsEvent statsEvent = StatsEvent.newBuilder()
.setAtomId(320)
.writeInt(Binder.getCallingUid())
@@ -85,6 +99,9 @@ public final class MediaMetricsManagerService extends SystemService {
@Override
public void reportPlaybackStateEvent(
String sessionId, PlaybackStateEvent event, int userId) {
+ if (!shouldWriteStats()) {
+ return;
+ }
StatsEvent statsEvent = StatsEvent.newBuilder()
.setAtomId(322)
.writeString(sessionId)
@@ -116,6 +133,9 @@ public final class MediaMetricsManagerService extends SystemService {
@Override
public void reportPlaybackErrorEvent(
String sessionId, PlaybackErrorEvent event, int userId) {
+ if (!shouldWriteStats()) {
+ return;
+ }
StatsEvent statsEvent = StatsEvent.newBuilder()
.setAtomId(323)
.writeString(sessionId)
@@ -130,6 +150,9 @@ public final class MediaMetricsManagerService extends SystemService {
public void reportNetworkEvent(
String sessionId, NetworkEvent event, int userId) {
+ if (!shouldWriteStats()) {
+ return;
+ }
StatsEvent statsEvent = StatsEvent.newBuilder()
.setAtomId(321)
.writeString(sessionId)
@@ -143,6 +166,9 @@ public final class MediaMetricsManagerService extends SystemService {
@Override
public void reportTrackChangeEvent(
String sessionId, TrackChangeEvent event, int userId) {
+ if (!shouldWriteStats()) {
+ return;
+ }
StatsEvent statsEvent = StatsEvent.newBuilder()
.setAtomId(324)
.writeString(sessionId)
@@ -165,5 +191,33 @@ public final class MediaMetricsManagerService extends SystemService {
.build();
StatsLog.write(statsEvent);
}
+
+ private boolean shouldWriteStats() {
+ int uid = Binder.getCallingUid();
+
+ final long identity = Binder.clearCallingIdentity();
+ int mode = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_MEDIA, MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_OFF);
+ Binder.restoreCallingIdentity(identity);
+
+ if (mode != MEDIA_METRICS_MODE_ON) {
+ return false;
+ }
+ if (mBlockList.isEmpty()) {
+ return true;
+ }
+
+ PackageManager pm = getContext().getPackageManager();
+ String[] packages = pm.getPackagesForUid(uid);
+ if (packages == null) {
+ // The valid application UID range is from android.os.Process.FIRST_APPLICATION_UID
+ // to android.os.Process.LAST_APPLICATION_UID.
+ // UIDs outside this range will not have a package and will therefore be false.
+ Slog.d(TAG, "null package from uid " + uid);
+ return false;
+ }
+ // TODO: check calling package with allowlist/blocklist.
+ return true;
+ }
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 4b4146683a09..654b17fb9754 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -26,6 +26,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
+import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.INVALID_UID;
import android.app.ActivityManager;
@@ -192,13 +193,12 @@ public class NetworkPolicyLogger {
}
}
- void tempPowerSaveWlChanged(int appId, boolean added) {
+ void tempPowerSaveWlChanged(int appId, boolean added, int reasonCode, String reason) {
synchronized (mLock) {
if (LOGV || appId == UserHandle.getAppId(mDebugUid)) {
- Slog.v(TAG,
- getTempPowerSaveWlChangedLog(appId, added));
+ Slog.v(TAG, getTempPowerSaveWlChangedLog(appId, added, reasonCode, reason));
}
- mEventsBuffer.tempPowerSaveWlChanged(appId, added);
+ mEventsBuffer.tempPowerSaveWlChanged(appId, added, reasonCode, reason);
}
}
@@ -326,8 +326,10 @@ public class NetworkPolicyLogger {
return "Parole state: " + paroleOn;
}
- private static String getTempPowerSaveWlChangedLog(int appId, boolean added) {
- return "temp-power-save whitelist for " + appId + " changed to: " + added;
+ private static String getTempPowerSaveWlChangedLog(int appId, boolean added,
+ int reasonCode, String reason) {
+ return "temp-power-save whitelist for " + appId + " changed to: " + added
+ + "; reason=" + reasonCodeToString(reasonCode) + " <" + reason + ">";
}
private static String getUidFirewallRuleChangedLog(int chain, int uid, int rule) {
@@ -497,14 +499,17 @@ public class NetworkPolicyLogger {
data.timeStamp = System.currentTimeMillis();
}
- public void tempPowerSaveWlChanged(int appId, boolean added) {
+ public void tempPowerSaveWlChanged(int appId, boolean added,
+ int reasonCode, String reason) {
final Data data = getNextSlot();
if (data == null) return;
data.reset();
data.type = EVENT_TEMP_POWER_SAVE_WL_CHANGED;
data.ifield1 = appId;
+ data.ifield2 = reasonCode;
data.bfield1 = added;
+ data.sfield1 = reason;
data.timeStamp = System.currentTimeMillis();
}
@@ -571,7 +576,8 @@ public class NetworkPolicyLogger {
case EVENT_PAROLE_STATE_CHANGED:
return getParoleStateChanged(data.bfield1);
case EVENT_TEMP_POWER_SAVE_WL_CHANGED:
- return getTempPowerSaveWlChangedLog(data.ifield1, data.bfield1);
+ return getTempPowerSaveWlChangedLog(data.ifield1, data.bfield1,
+ data.ifield2, data.sfield1);
case EVENT_UID_FIREWALL_RULE_CHANGED:
return getUidFirewallRuleChangedLog(data.ifield1, data.ifield2, data.ifield3);
case EVENT_FIREWALL_CHAIN_ENABLED:
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 2e4d41c7d364..03a63b9058a8 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -17,9 +17,11 @@
package com.android.server.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.Network;
import android.net.NetworkTemplate;
import android.net.netstats.provider.NetworkStatsProvider;
+import android.os.PowerExemptionManager.ReasonCode;
import android.telephony.SubscriptionPlan;
import java.util.Set;
@@ -41,9 +43,13 @@ public abstract class NetworkPolicyManagerInternal {
* that network rules for that appId can be updated.
*
* @param appId The appId which has been updated in the allowlist.
- * @param added Denotes whether the {@param appId} has been added or removed from the allowlist.
+ * @param added Denotes whether the {@code appId} has been added or removed from the allowlist.
+ * @param reasonCode one of {@link ReasonCode} indicating the reason for the change.
+ * Only valid when {@code added} is {@code true}.
+ * @param reason an optional human-readable reason explaining why the app is temp allow-listed.
*/
- public abstract void onTempPowerSaveWhitelistChange(int appId, boolean added);
+ public abstract void onTempPowerSaveWhitelistChange(int appId, boolean added,
+ @ReasonCode int reasonCode, @Nullable String reason);
/**
* Return the active {@link SubscriptionPlan} for the given network.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index cfd575080d97..21f68aecd25b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -211,6 +211,7 @@ import android.os.Message;
import android.os.MessageQueue.IdleHandler;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
+import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
@@ -5743,12 +5744,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
- public void onTempPowerSaveWhitelistChange(int appId, boolean added) {
+ public void onTempPowerSaveWhitelistChange(int appId, boolean added,
+ @ReasonCode int reasonCode, @Nullable String reason) {
synchronized (mUidRulesFirstLock) {
if (!mSystemReady) {
return;
}
- mLogger.tempPowerSaveWlChanged(appId, added);
+ mLogger.tempPowerSaveWlChanged(appId, added, reasonCode, reason);
if (added) {
mPowerSaveTempWhitelistAppIds.put(appId, true);
} else {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c1e29ebc4703..6d51849ea513 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2910,6 +2910,7 @@ public class WindowManagerService extends IWindowManager.Stub
+ " for the display " + displayId + " that does not exist.");
return;
}
+ remoteAnimationAdapter.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
displayContent.mAppTransition.overridePendingAppTransitionRemote(
remoteAnimationAdapter);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index d5e1cd6e0415..21de7916e23d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -58,7 +58,8 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
-import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_CHANGED;
+import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED;
+import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_EXACT_ALARMS;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
@@ -103,10 +104,8 @@ import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -155,6 +154,8 @@ import com.android.server.AppStateTrackerImpl;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.usage.AppStandbyInternal;
@@ -175,6 +176,7 @@ import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -370,8 +372,9 @@ public class AlarmManagerServiceTest {
.mockStatic(LocalServices.class)
.spyStatic(Looper.class)
.mockStatic(MetricsHelper.class)
- .mockStatic(Settings.Global.class)
+ .mockStatic(PermissionManagerService.class)
.mockStatic(ServiceManager.class)
+ .mockStatic(Settings.Global.class)
.mockStatic(SystemProperties.class)
.spyStatic(UserHandle.class)
.strictness(Strictness.WARN)
@@ -394,7 +397,7 @@ public class AlarmManagerServiceTest {
doCallRealMethod().when((MockedVoidMethod) () ->
LocalServices.addService(eq(AlarmManagerInternal.class), any()));
doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class));
- doReturn(false).when(() -> UserHandle.isCore(TEST_CALLING_UID));
+ doReturn(false).when(() -> UserHandle.isCore(anyInt()));
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
eq(TEST_CALLING_USER), anyLong())).thenReturn(STANDBY_BUCKET_ACTIVE);
doReturn(Looper.getMainLooper()).when(Looper::myLooper);
@@ -983,8 +986,7 @@ public class AlarmManagerServiceTest {
verify(mService.mHandler, atLeastOnce()).sendMessageAtTime(messageCaptor.capture(),
anyLong());
final Message lastMessage = messageCaptor.getValue();
- assertEquals("Unexpected message send to handler", lastMessage.what,
- what);
+ assertEquals("Unexpected message send to handler", what, lastMessage.what);
mService.mHandler.handleMessage(lastMessage);
}
@@ -1876,6 +1878,8 @@ public class AlarmManagerServiceTest {
@Test
public void hasScheduleExactAlarmBinderCallNotDenyListed() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
mockExactAlarmPermissionGrant(true, false, MODE_DEFAULT);
assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
@@ -1891,6 +1895,8 @@ public class AlarmManagerServiceTest {
@Test
public void hasScheduleExactAlarmBinderCallDenyListed() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
mockExactAlarmPermissionGrant(true, true, MODE_ERRORED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
@@ -1905,7 +1911,25 @@ public class AlarmManagerServiceTest {
}
@Test
+ public void hasScheduleExactAlarmBinderCallChangeDisabled() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
+
+ mockExactAlarmPermissionGrant(true, false, MODE_DEFAULT);
+ assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
+
+ mockExactAlarmPermissionGrant(true, true, MODE_ALLOWED);
+ assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
+ }
+
+ private void mockChangeEnabled(long changeId, boolean enabled) {
+ doReturn(enabled).when(() -> CompatChanges.isChangeEnabled(eq(changeId), anyString(),
+ any(UserHandle.class)));
+ }
+
+ @Test
public void hasScheduleExactAlarmBinderCallNotDeclared() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
mockExactAlarmPermissionGrant(false, false, MODE_DEFAULT);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
@@ -1918,9 +1942,7 @@ public class AlarmManagerServiceTest {
@Test
public void noPermissionCheckWhenChangeDisabled() throws RemoteException {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
// alarm clock
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 0,
@@ -1946,9 +1968,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
@@ -1963,9 +1983,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
@@ -1985,9 +2003,7 @@ public class AlarmManagerServiceTest {
@Test
public void inexactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_HEURISTIC, 0,
@@ -2006,9 +2022,7 @@ public class AlarmManagerServiceTest {
@Test
public void alarmClockBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class);
@@ -2023,9 +2037,7 @@ public class AlarmManagerServiceTest {
@Test
public void alarmClockBinderCall() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
@@ -2060,7 +2072,6 @@ public class AlarmManagerServiceTest {
} else {
setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "");
}
-
when(mAppOpsManager.checkOpNoThrow(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID,
TEST_CALLING_PACKAGE)).thenReturn(mode);
}
@@ -2068,9 +2079,7 @@ public class AlarmManagerServiceTest {
@Test
public void alarmClockBinderCallWithoutPermission() throws RemoteException {
setDeviceConfigBoolean(KEY_CRASH_NON_CLOCK_APPS, true);
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2089,9 +2098,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactBinderCallWithPermission() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2115,9 +2122,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactBinderCallWithAllowlist() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// If permission is denied, only then allowlist will be checked.
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2137,9 +2142,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2162,9 +2165,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// If permission is denied, only then allowlist will be checked.
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2191,9 +2192,7 @@ public class AlarmManagerServiceTest {
@Test
public void exactBinderCallsWithoutPermissionWithoutAllowlist() throws RemoteException {
setDeviceConfigBoolean(KEY_CRASH_NON_CLOCK_APPS, true);
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
@@ -2220,9 +2219,7 @@ public class AlarmManagerServiceTest {
public void inexactAllowWhileIdleBinderCall() throws RemoteException {
// Both permission and power exemption status don't matter for these alarms.
// We only want to test that the flags and idleOptions are correct.
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 4321, WINDOW_HEURISTIC, 0,
@@ -2244,9 +2241,7 @@ public class AlarmManagerServiceTest {
@Test
public void binderCallWithUserAllowlist() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2266,10 +2261,7 @@ public class AlarmManagerServiceTest {
@Test
public void minWindowChangeEnabled() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(
- eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
final int minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
@@ -2315,10 +2307,7 @@ public class AlarmManagerServiceTest {
@Test
public void minWindowChangeDisabled() {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(
- eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, false);
final long minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
@@ -2335,10 +2324,7 @@ public class AlarmManagerServiceTest {
@Test
public void minWindowPriorityAlarm() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(
- eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
final long minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
@@ -2356,76 +2342,135 @@ public class AlarmManagerServiceTest {
}
@Test
- public void denyListPackagesAdded() {
+ public void denyListChanged() {
mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"});
+ when(mActivityManagerInternal.getStartedUserIds()).thenReturn(EmptyArray.INT);
+
setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "p2,p4,p5");
- assertAndHandleMessageSync(EXACT_ALARM_DENY_LIST_CHANGED);
+
+ final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mService.mHandler, times(2)).sendMessageAtTime(messageCaptor.capture(),
+ anyLong());
+
+ final List<Message> messages = messageCaptor.getAllValues();
+ for (final Message msg : messages) {
+ assertTrue("Unwanted message sent to handler: " + msg.what,
+ msg.what == EXACT_ALARM_DENY_LIST_PACKAGES_ADDED
+ || msg.what == EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED);
+ mService.mHandler.handleMessage(msg);
+ }
ArraySet<String> added = new ArraySet<>(new String[]{"p4", "p5"});
- verify(mService).handlePackagesAddedToExactAlarmsDenyListLocked(eq(added));
+ verify(mService).handleChangesToExactAlarmDenyList(eq(added), eq(true));
+
+ ArraySet<String> removed = new ArraySet<>(new String[]{"p1", "p3"});
+ verify(mService).handleChangesToExactAlarmDenyList(eq(removed), eq(false));
}
@Test
- public void denyListPackagesRemoved() {
- clearInvocations(mService.mHandler);
- mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"});
- setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "p2");
- verifyNoMoreInteractions(mService.mHandler);
+ public void permissionGrantedDueToDenyList() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
+ final String[] packages = {"example.package.1", "example.package.2"};
+
+ final int appId1 = 232;
+ final int appId2 = 431;
+
+ final int userId1 = 42;
+ final int userId2 = 53;
+
+ registerAppIds(packages, new Integer[]{appId1, appId2});
+
+ when(mActivityManagerInternal.getStartedUserIds()).thenReturn(new int[]{userId1, userId2});
+
+ when(mPermissionManagerInternal.getAppOpPermissionPackages(
+ SCHEDULE_EXACT_ALARM)).thenReturn(packages);
+ mService.refreshExactAlarmCandidates();
+
+ final long allowListDuration = 53442;
+ when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(
+ allowListDuration);
+
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId1), MODE_ALLOWED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId1), MODE_DEFAULT);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId2), MODE_IGNORED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId2), MODE_ERRORED);
+
+ mService.handleChangesToExactAlarmDenyList(new ArraySet<>(packages), false);
+
+ // No permission revoked.
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(anyInt(), anyString());
+
+ // Permission got granted only for (appId1, userId2).
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ final ArgumentCaptor<UserHandle> userCaptor = ArgumentCaptor.forClass(UserHandle.class);
+
+ verify(mMockContext).sendBroadcastAsUser(intentCaptor.capture(), userCaptor.capture(),
+ isNull(), bundleCaptor.capture());
+
+ assertEquals(userId2, userCaptor.getValue().getIdentifier());
+
+ // Validate the intent.
+ assertEquals(AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED,
+ intentCaptor.getValue().getAction());
+ assertEquals(packages[0], intentCaptor.getValue().getPackage());
+
+ // Validate the options.
+ final BroadcastOptions bOptions = new BroadcastOptions(bundleCaptor.getValue());
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ bOptions.getTemporaryAppAllowlistType());
+ assertEquals(allowListDuration, bOptions.getTemporaryAppAllowlistDuration());
+ assertEquals(PowerExemptionManager.REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED,
+ bOptions.getTemporaryAppAllowlistReasonCode());
}
@Test
- public void removeExactAlarmsOnPackageAddedToDenyList() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ public void permissionRevokedDueToDenyList() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- // basic exact alarm
- setTestAlarm(ELAPSED_REALTIME, 1, 0, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID,
- null);
- // exact and allow-while-idle alarm
- setTestAlarm(ELAPSED_REALTIME, 2, 0, getNewMockPendingIntent(), 0, FLAG_ALLOW_WHILE_IDLE,
- TEST_CALLING_UID, null);
- // alarm clock
- setWakeFromIdle(RTC_WAKEUP, 3, getNewMockPendingIntent());
+ final String[] packages = {"example.package.1", "example.package.2"};
- final PendingIntent inexact = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 4, 10, inexact, 0, 0, TEST_CALLING_UID, null);
+ final int appId1 = 232;
+ final int appId2 = 431;
- final PendingIntent inexactAwi = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 5, 10, inexactAwi, 0, FLAG_ALLOW_WHILE_IDLE,
- TEST_CALLING_UID, null);
+ final int userId1 = 42;
+ final int userId2 = 53;
- final String differentPackage = "different.package";
- final PendingIntent exactButDifferentPackage = getNewMockPendingIntent(
- TEST_CALLING_UID, differentPackage);
- setTestAlarm(ELAPSED_REALTIME, 6, 0, exactButDifferentPackage, 0, 0,
- TEST_CALLING_UID, differentPackage, null);
- assertEquals(6, mService.mAlarmStore.size());
+ registerAppIds(packages, new Integer[]{appId1, appId2});
- when(mAppOpsManager.checkOpNoThrow(eq(OP_SCHEDULE_EXACT_ALARM), anyInt(),
- anyString())).thenReturn(MODE_DEFAULT);
- setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, TEST_CALLING_PACKAGE);
- assertAndHandleMessageSync(EXACT_ALARM_DENY_LIST_CHANGED);
- verify(mService).handlePackagesAddedToExactAlarmsDenyListLocked(
- argThat(set -> (set.size() == 1 && set.contains(TEST_CALLING_PACKAGE))));
+ when(mActivityManagerInternal.getStartedUserIds()).thenReturn(new int[]{userId1, userId2});
- final ArrayList<Alarm> remaining = mService.mAlarmStore.asList();
- assertEquals(3, remaining.size());
- assertTrue("Basic inexact alarm removed",
- remaining.removeIf(a -> a.matches(inexact, null)));
- assertTrue("Inexact allow-while-idle alarm removed",
- remaining.removeIf(a -> a.matches(inexactAwi, null)));
- assertTrue("Alarm from different package removed",
- remaining.removeIf(a -> a.matches(exactButDifferentPackage, null)));
+ when(mPermissionManagerInternal.getAppOpPermissionPackages(
+ SCHEDULE_EXACT_ALARM)).thenReturn(packages);
+ mService.refreshExactAlarmCandidates();
- // Mock should return false by default.
- verify(mDeviceIdleInternal, atLeastOnce()).isAppOnWhitelist(
- UserHandle.getAppId(TEST_CALLING_UID));
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId1), MODE_ALLOWED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId1), MODE_DEFAULT);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId2), MODE_IGNORED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId2), MODE_ERRORED);
+
+ mService.handleChangesToExactAlarmDenyList(new ArraySet<>(packages), true);
+
+ // Permission got revoked only for (appId1, userId2)
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId1, appId1)), eq(packages[0]));
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId1, appId2)), eq(packages[1]));
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId2, appId2)), eq(packages[1]));
+
+ verify(mService).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId2, appId1)), eq(packages[0]));
}
@Test
- public void opScheduleExactAlarmRevoked() throws Exception {
+ public void opChangedPermissionRevoked() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
assertAndHandleMessageSync(REMOVE_EXACT_ALARMS);
verify(mService).removeExactAlarmsOnPermissionRevokedLocked(TEST_CALLING_UID,
@@ -2433,10 +2478,39 @@ public class AlarmManagerServiceTest {
}
@Test
- public void opScheduleExactAlarmGranted() throws Exception {
+ public void opChangedChangeDisabled() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
+
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED);
+ mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+
+ mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+
+ verify(mService.mHandler, never()).sendMessageAtTime(
+ argThat(m -> m.what == REMOVE_EXACT_ALARMS), anyLong());
+ }
+
+ @Test
+ public void opChangedNoPermissionChangeDueToDenyList() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
+
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED);
+ mockExactAlarmPermissionGrant(true, true, MODE_DEFAULT);
+
+ mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+
+ verify(mService.mHandler, never()).sendMessageAtTime(
+ argThat(m -> m.what == REMOVE_EXACT_ALARMS), anyLong());
+ }
+
+ @Test
+ public void opChangedPermissionGranted() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
final long durationMs = 20000L;
when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(durationMs);
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
@@ -2462,9 +2536,7 @@ public class AlarmManagerServiceTest {
@Test
public void removeExactAlarmsOnPermissionRevoked() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// basic exact alarm
setTestAlarm(ELAPSED_REALTIME, 0, 0, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID,
@@ -2501,6 +2573,9 @@ public class AlarmManagerServiceTest {
// Mock should return false by default.
verify(mDeviceIdleInternal, atLeastOnce()).isAppOnWhitelist(
UserHandle.getAppId(TEST_CALLING_UID));
+
+ verify(() -> PermissionManagerService.killUid(eq(TEST_CALLING_UID), eq(TEST_CALLING_USER),
+ anyString()));
}
@Test
@@ -2567,6 +2642,86 @@ public class AlarmManagerServiceTest {
}
@Test
+ public void onLastOpScheduleExactAlarmOnUserStart() {
+ final int userId = 54;
+ SystemService.TargetUser mockTargetUser = mock(SystemService.TargetUser.class);
+ when(mockTargetUser.getUserIdentifier()).thenReturn(userId);
+
+ final Integer[] appIds = new Integer[]{43, 254, 7731};
+ final int unknownAppId = 2347;
+ final String[] packageNames = new String[]{"p43", "p254", "p7731"};
+ final int[] appOpModes = new int[]{MODE_ALLOWED, MODE_IGNORED, MODE_ERRORED};
+ mService.mExactAlarmCandidates = new ArraySet<>(appIds);
+ mService.mExactAlarmCandidates.add(unknownAppId);
+
+ for (int i = 0; i < appIds.length; i++) {
+ final int uid = UserHandle.getUid(userId, appIds[i]);
+ final AndroidPackage pkg = mock(AndroidPackage.class);
+ when(pkg.getPackageName()).thenReturn(packageNames[i]);
+
+ when(mPackageManagerInternal.getPackage(uid)).thenReturn(pkg);
+ when(mAppOpsManager.checkOpNoThrow(OP_SCHEDULE_EXACT_ALARM, uid,
+ packageNames[i])).thenReturn(appOpModes[i]);
+ }
+
+ final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ doReturn(true).when(mService.mHandler).post(runnableCaptor.capture());
+
+ mService.onUserStarting(mockTargetUser);
+ runnableCaptor.getValue().run();
+
+ assertEquals(appIds.length, mService.mLastOpScheduleExactAlarm.size());
+ for (int i = 0; i < appIds.length; i++) {
+ final int uid = UserHandle.getUid(userId, appIds[i]);
+ assertEquals(appOpModes[i], mService.mLastOpScheduleExactAlarm.get(uid, -1));
+ }
+ assertTrue(mService.mLastOpScheduleExactAlarm.indexOfKey(
+ UserHandle.getUid(userId, unknownAppId)) < 0);
+ }
+
+ @Test
+ public void refreshExactAlarmCandidatesRemovesExactAlarmsIfNeeded() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
+ mService.mExactAlarmCandidates = new ArraySet<>(new Integer[]{1, 2, 5});
+ final String[] updatedRequesters = new String[]{"p11", "p2", "p9"};
+ final Integer[] appIds = new Integer[]{11, 2, 9};
+ registerAppIds(updatedRequesters, appIds);
+
+ when(mPermissionManagerInternal.getAppOpPermissionPackages(
+ SCHEDULE_EXACT_ALARM)).thenReturn(updatedRequesters);
+
+ final PendingIntent exactAppId1 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId1, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 1), null);
+
+ final PendingIntent exactAppId2 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId2, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 2), null);
+
+ final PendingIntent exactAppId5 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId5, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 5), null);
+
+ final PendingIntent inexactAppId5 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 23, inexactAppId5, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 5), null);
+
+ assertEquals(4, mService.mAlarmStore.size());
+
+ mService.refreshExactAlarmCandidates();
+ // App ids 1 and 5 lost the permission, so there alarms should be removed.
+
+ final ArrayList<Alarm> remaining = mService.mAlarmStore.asList();
+ assertEquals(2, remaining.size());
+
+ assertTrue("Inexact alarm removed",
+ remaining.removeIf(a -> a.matches(inexactAppId5, null)));
+ assertTrue("Alarm from app id 2 removed",
+ remaining.removeIf(a -> a.matches(exactAppId2, null)));
+ }
+
+ @Test
public void refreshExactAlarmCandidatesOnPackageAdded() {
final String[] exactAlarmRequesters = new String[]{"p11", "p2", "p9"};
final Integer[] appIds = new Integer[]{11, 2, 9};
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 6f0c8e1004c4..aec70f4f3df0 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
import static junit.framework.Assert.assertEquals;
@@ -234,6 +236,27 @@ public class AuthServiceTest {
eq(mReceiver),
eq(TEST_OP_PACKAGE_NAME),
eq(promptInfo));
+ verify(mReceiver).onError(eq(TYPE_NONE), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
+ }
+
+ @Test
+ public void testAuthenticate_missingRequiredParam() throws Exception {
+ mAuthService = new AuthService(mContext, mInjector);
+ mAuthService.onStart();
+
+ final PromptInfo promptInfo = new PromptInfo();
+ final long sessionId = 0;
+ final int userId = 0;
+
+ mAuthService.mImpl.authenticate(
+ null /* token */,
+ sessionId,
+ userId,
+ mReceiver,
+ TEST_OP_PACKAGE_NAME,
+ promptInfo);
+ waitForIdle();
+ verify(mReceiver).onError(eq(TYPE_NONE), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
}
@Test
@@ -259,7 +282,6 @@ public class AuthServiceTest {
eq(authenticators));
}
-
@Test
public void testHasEnrolledBiometrics_callsBiometricServiceHasEnrolledBiometrics() throws
Exception {
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index ea5a43104bba..e07fbbf7a1c1 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -27,6 +27,7 @@ android_test {
libs: ["android.test.runner"],
static_libs: [
"androidx.test.ext.junit",
+ "androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
"platform-test-annotations",
"truth-prebuilt",
diff --git a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml
index 5d8f5fc2da93..8c3d87698e17 100644
--- a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml
+++ b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml
@@ -19,5 +19,6 @@
package="com.android.emojirenderingtestapp">
<application>
<activity android:name=".EmojiRenderingTestActivity"/>
+ <activity android:name=".GetAvailableFontsTestActivity"/>
</application>
</manifest>
diff --git a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java
new file mode 100644
index 000000000000..b9a91490f517
--- /dev/null
+++ b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.emojirenderingtestapp;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.app.Activity;
+import android.graphics.fonts.Font;
+import android.graphics.fonts.SystemFonts;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class GetAvailableFontsTestActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String emojiFontPath = "<Not found>";
+ for (Font font : SystemFonts.getAvailableFonts()) {
+ // Calls font attribute getters to make sure that they don't open font files.
+ font.getAxes();
+ font.getFile();
+ font.getLocaleList();
+ font.getStyle();
+ font.getTtcIndex();
+ if ("NotoColorEmoji.ttf".equals(font.getFile().getName())) {
+ emojiFontPath = font.getFile().getAbsolutePath();
+ }
+ }
+ LinearLayout container = new LinearLayout(this);
+ container.setOrientation(LinearLayout.VERTICAL);
+ TextView textView = new TextView(this);
+ textView.setText(emojiFontPath);
+ container.addView(textView, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ setContentView(container);
+ }
+}
diff --git a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
index 80b0dfeb8804..6bd07d0a84fd 100644
--- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
+++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
@@ -40,6 +40,9 @@ import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
import com.android.compatibility.common.util.StreamUtil;
import com.android.compatibility.common.util.SystemUtil;
@@ -101,6 +104,9 @@ public class UpdatableSystemFontTest {
EMOJI_RENDERING_TEST_APP_ID + "/.EmojiRenderingTestActivity";
private static final long ACTIVITY_TIMEOUT_MILLIS = SECONDS.toMillis(10);
+ private static final String GET_AVAILABLE_FONTS_TEST_ACTIVITY =
+ EMOJI_RENDERING_TEST_APP_ID + "/.GetAvailableFontsTestActivity";
+
private static final Pattern PATTERN_FONT_FILES = Pattern.compile("\\.(ttf|otf|ttc|otc)$");
private static final Pattern PATTERN_TMP_FILES = Pattern.compile("^/data/local/tmp/");
private static final Pattern PATTERN_DATA_FONT_FILES = Pattern.compile("^/data/fonts/files/");
@@ -109,6 +115,7 @@ public class UpdatableSystemFontTest {
private String mKeyId;
private FontManager mFontManager;
+ private UiDevice mUiDevice;
@Before
public void setUp() throws Exception {
@@ -120,6 +127,7 @@ public class UpdatableSystemFontTest {
mKeyId = insertCert(CERT_PATH);
mFontManager = context.getSystemService(FontManager.class);
expectCommandToSucceed("cmd font clear");
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
@After
@@ -287,6 +295,19 @@ public class UpdatableSystemFontTest {
assertThat(countMatch(openFiles, patternEmojiVPlus1)).isEqualTo(0);
}
+ @Test
+ public void getAvailableFonts() throws Exception {
+ String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME);
+ startActivity(EMOJI_RENDERING_TEST_APP_ID, GET_AVAILABLE_FONTS_TEST_ACTIVITY);
+ // GET_AVAILABLE_FONTS_TEST_ACTIVITY shows the NotoColorEmoji path it got.
+ mUiDevice.wait(
+ Until.findObject(By.pkg(EMOJI_RENDERING_TEST_APP_ID).text(fontPath)),
+ ACTIVITY_TIMEOUT_MILLIS);
+ // The font file should not be opened just by querying the path using
+ // SystemFont.getAvailableFonts().
+ assertThat(isFileOpenedBy(fontPath, EMOJI_RENDERING_TEST_APP_ID)).isFalse();
+ }
+
private static String insertCert(String certPath) throws Exception {
Pair<String, String> result;
try (InputStream is = new FileInputStream(certPath)) {