summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java9
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java41
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java7
-rw-r--r--core/api/current.txt1
-rw-r--r--core/api/system-current.txt1
-rw-r--r--core/java/android/app/AppOpsManager.java1
-rw-r--r--core/java/android/hardware/face/FaceManager.java40
-rw-r--r--core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl35
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl9
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl2
-rw-r--r--core/java/android/os/BatteryStats.java7
-rw-r--r--core/java/android/service/notification/NotificationAssistantService.java15
-rw-r--r--core/java/android/view/ViewRootImpl.java27
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java37
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java72
-rw-r--r--core/java/android/view/accessibility/DirectAccessibilityConnection.java136
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java1316
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistoryIterator.java8
-rw-r--r--core/jni/android/opengl/util.cpp51
-rw-r--r--libs/WindowManager/Shell/res/layout/tv_pip_menu.xml153
-rw-r--r--libs/WindowManager/Shell/res/values/colors_tv.xml1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java11
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt7
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/MultiWindowHelper.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt13
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt4
-rw-r--r--libs/hwui/hwui/Typeface.cpp9
-rw-r--r--libs/hwui/hwui/Typeface.h3
-rw-r--r--libs/hwui/jni/Typeface.cpp25
-rw-r--r--libs/hwui/renderthread/VulkanManager.h2
-rw-r--r--libs/hwui/tests/unit/TypefaceTests.cpp67
-rw-r--r--native/android/system_fonts.cpp41
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt11
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt11
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt2
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt10
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt15
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt15
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt15
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt1
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt46
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/RegularScaffold.kt83
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppOpsController.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRecord.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRecord.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRepository.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/Apps.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/PackageManagers.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/EnterpriseRepository.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/enterprise/EnterpriseRepository.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt4
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt4
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/WorkProfilePager.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/WorkProfilePager.kt)4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java92
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java116
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java392
-rw-r--r--services/core/java/com/android/server/appop/AppOpsServiceInterface.java99
-rw-r--r--services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java379
-rw-r--r--services/core/java/com/android/server/appop/OnOpModeChangedListener.java102
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java61
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java243
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java94
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java221
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java71
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java30
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java373
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java72
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java37
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java5
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java7
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java2
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java1796
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java16
-rw-r--r--services/core/java/com/android/server/wm/AppWarnings.java53
-rw-r--r--services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java27
-rw-r--r--services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java20
-rw-r--r--services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java24
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java106
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java172
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java51
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java168
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java9
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt40
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt11
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt26
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt20
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt30
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt16
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt18
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt16
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt24
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt6
-rw-r--r--tools/lint/Android.bp6
-rw-r--r--tools/lint/README.md4
-rw-r--r--tools/lint/fix/README.md46
-rw-r--r--tools/lint/fix/lint_fix.py76
160 files changed, 4777 insertions, 3294 deletions
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 448ee6160ce0..cd86d6a4d6c7 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -273,9 +273,7 @@ public class UserLifecycleTests {
mRunner.resumeTiming();
Log.i(TAG, "Starting timer");
- runThenWaitForBroadcasts(testUser, () -> {
- mAm.switchUser(testUser);
- }, Intent.ACTION_USER_UNLOCKED);
+ switchUser(testUser);
mRunner.pauseTiming();
Log.i(TAG, "Stopping timer");
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
index 59cd82e971bf..3bbc5a369684 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -176,12 +176,13 @@ public final class BatteryController extends RestrictingController {
Slog.d(TAG, "maybeReportNewChargingStateLocked: "
+ powerConnected + "/" + stablePower + "/" + batteryNotLow);
}
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+
mFlexibilityController.setConstraintSatisfied(
- JobStatus.CONSTRAINT_CHARGING, mService.isBatteryCharging());
- mFlexibilityController
- .setConstraintSatisfied(JobStatus.CONSTRAINT_BATTERY_NOT_LOW, batteryNotLow);
+ JobStatus.CONSTRAINT_CHARGING, mService.isBatteryCharging(), nowElapsed);
+ mFlexibilityController.setConstraintSatisfied(
+ JobStatus.CONSTRAINT_BATTERY_NOT_LOW, batteryNotLow, nowElapsed);
- final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
final JobStatus ts = mTrackedTasks.valueAt(i);
if (ts.hasChargingConstraint()) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
index 2e41dfd2888c..3ca1ad58955d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -137,9 +137,9 @@ public final class FlexibilityController extends StateController {
new PrefetchController.PrefetchChangedListener() {
@Override
public void onPrefetchCacheUpdated(ArraySet<JobStatus> jobs, int userId,
- String pkgName, long prevEstimatedLaunchTime, long newEstimatedLaunchTime) {
+ String pkgName, long prevEstimatedLaunchTime,
+ long newEstimatedLaunchTime, long nowElapsed) {
synchronized (mLock) {
- final long nowElapsed = sElapsedRealtimeClock.millis();
final long prefetchThreshold =
mPrefetchController.getLaunchTimeThresholdMs();
boolean jobWasInPrefetchWindow = prevEstimatedLaunchTime
@@ -158,8 +158,8 @@ public final class FlexibilityController extends StateController {
if (!js.hasFlexibilityConstraint()) {
continue;
}
- mFlexibilityTracker.resetJobNumDroppedConstraints(js);
- mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
+ mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
}
}
}
@@ -191,7 +191,7 @@ public final class FlexibilityController extends StateController {
js.setTrackingController(JobStatus.TRACKING_FLEXIBILITY);
final long nowElapsed = sElapsedRealtimeClock.millis();
js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
- mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
+ mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
}
}
@@ -239,7 +239,7 @@ public final class FlexibilityController extends StateController {
* Changes flexibility constraint satisfaction for affected jobs.
*/
@VisibleForTesting
- void setConstraintSatisfied(int constraint, boolean state) {
+ void setConstraintSatisfied(int constraint, boolean state, long nowElapsed) {
synchronized (mLock) {
final boolean old = (mSatisfiedFlexibleConstraints & constraint) != 0;
if (old == state) {
@@ -255,8 +255,6 @@ public final class FlexibilityController extends StateController {
// The rest did not have a change in state and are still satisfied or unsatisfied.
final int numConstraintsToUpdate = Math.max(curSatisfied, prevSatisfied);
- final long nowElapsed = sElapsedRealtimeClock.millis();
-
// In order to get the range of all potentially satisfied jobs, we start at the number
// of satisfied system-wide constraints and iterate to the max number of potentially
// satisfied constraints, determined by how many job-specific constraints exist.
@@ -329,10 +327,9 @@ public final class FlexibilityController extends StateController {
@VisibleForTesting
@GuardedBy("mLock")
- int getCurPercentOfLifecycleLocked(JobStatus js) {
+ int getCurPercentOfLifecycleLocked(JobStatus js, long nowElapsed) {
final long earliest = getLifeCycleBeginningElapsedLocked(js);
final long latest = getLifeCycleEndElapsedLocked(js, earliest);
- final long nowElapsed = sElapsedRealtimeClock.millis();
if (latest == NO_LIFECYCLE_END || earliest >= nowElapsed) {
return 0;
}
@@ -414,8 +411,8 @@ public final class FlexibilityController extends StateController {
.getJobsByNumRequiredConstraints(j);
for (int i = 0; i < jobs.size(); i++) {
JobStatus js = jobs.valueAt(i);
- mFlexibilityTracker.resetJobNumDroppedConstraints(js);
- mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
+ mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
if (js.setFlexibilityConstraintSatisfied(
nowElapsed, isFlexibilitySatisfiedLocked(js))) {
changedJobs.add(js);
@@ -479,8 +476,8 @@ public final class FlexibilityController extends StateController {
mTrackedJobs.get(js.getNumRequiredFlexibleConstraints() - 1).remove(js);
}
- public void resetJobNumDroppedConstraints(JobStatus js) {
- final int curPercent = getCurPercentOfLifecycleLocked(js);
+ public void resetJobNumDroppedConstraints(JobStatus js, long nowElapsed) {
+ final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
int toDrop = 0;
final int jsMaxFlexibleConstraints = NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
+ (js.getPreferUnmetered() ? 1 : 0);
@@ -489,7 +486,8 @@ public final class FlexibilityController extends StateController {
toDrop++;
}
}
- adjustJobsRequiredConstraints(js, js.getNumDroppedFlexibleConstraints() - toDrop);
+ adjustJobsRequiredConstraints(
+ js, js.getNumDroppedFlexibleConstraints() - toDrop, nowElapsed);
}
/** Returns all tracked jobs. */
@@ -502,13 +500,12 @@ public final class FlexibilityController extends StateController {
* Returns false if the job status's number of flexible constraints is now 0.
* Jobs with 0 required flexible constraints are removed from the tracker.
*/
- public boolean adjustJobsRequiredConstraints(JobStatus js, int n) {
+ public boolean adjustJobsRequiredConstraints(JobStatus js, int n, long nowElapsed) {
if (n == 0) {
return false;
}
remove(js);
js.adjustNumRequiredFlexibleConstraints(n);
- final long nowElapsed = sElapsedRealtimeClock.millis();
js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
if (js.getNumRequiredFlexibleConstraints() <= 0) {
maybeStopTrackingJobLocked(js, null, false);
@@ -553,7 +550,7 @@ public final class FlexibilityController extends StateController {
return js.getSourceUserId() == userId;
}
- public void scheduleDropNumConstraintsAlarm(JobStatus js) {
+ public void scheduleDropNumConstraintsAlarm(JobStatus js, long nowElapsed) {
long nextTimeElapsed;
synchronized (mLock) {
final long earliest = getLifeCycleBeginningElapsedLocked(js);
@@ -567,7 +564,7 @@ public final class FlexibilityController extends StateController {
if (latest - nextTimeElapsed < mDeadlineProximityLimitMs) {
mFlexibilityTracker.adjustJobsRequiredConstraints(
- js, -js.getNumRequiredFlexibleConstraints());
+ js, -js.getNumRequiredFlexibleConstraints(), nowElapsed);
return;
}
addAlarm(js, nextTimeElapsed);
@@ -578,21 +575,21 @@ public final class FlexibilityController extends StateController {
protected void processExpiredAlarms(@NonNull ArraySet<JobStatus> expired) {
synchronized (mLock) {
ArraySet<JobStatus> changedJobs = new ArraySet<>();
+ final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = 0; i < expired.size(); i++) {
JobStatus js = expired.valueAt(i);
boolean wasFlexibilitySatisfied = js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE);
final long earliest = getLifeCycleBeginningElapsedLocked(js);
final long latest = getLifeCycleEndElapsedLocked(js, earliest);
- final long nowElapsed = sElapsedRealtimeClock.millis();
if (latest - nowElapsed < mDeadlineProximityLimitMs) {
mFlexibilityTracker.adjustJobsRequiredConstraints(js,
- -js.getNumRequiredFlexibleConstraints());
+ -js.getNumRequiredFlexibleConstraints(), nowElapsed);
} else {
long nextTimeElapsed =
getNextConstraintDropTimeElapsedLocked(js, earliest, latest);
- if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1)
+ if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1, nowElapsed)
&& nextTimeElapsed != NO_LIFECYCLE_END) {
mFlexibilityAlarmQueue.addAlarm(js, nextTimeElapsed);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
index d5750f8d7974..dd0621728724 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -95,9 +95,10 @@ public final class IdleController extends RestrictingController implements Idlen
*/
@Override
public void reportNewIdleState(boolean isIdle) {
- mFlexibilityController.setConstraintSatisfied(JobStatus.CONSTRAINT_IDLE, isIdle);
synchronized (mLock) {
final long nowElapsed = sElapsedRealtimeClock.millis();
+ mFlexibilityController.setConstraintSatisfied(
+ JobStatus.CONSTRAINT_IDLE, isIdle, nowElapsed);
for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(nowElapsed, isIdle);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
index 0945b7e796fd..e04cec30d26b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
@@ -105,7 +105,7 @@ public class PrefetchController extends StateController {
public interface PrefetchChangedListener {
/** Callback to inform listeners when estimated launch times change. */
void onPrefetchCacheUpdated(ArraySet<JobStatus> jobs, int userId, String pkgName,
- long prevEstimatedLaunchTime, long newEstimatedLaunchTime);
+ long prevEstimatedLaunchTime, long newEstimatedLaunchTime, long nowElapsed);
}
@SuppressWarnings("FieldCanBeLocal")
@@ -308,8 +308,9 @@ public class PrefetchController extends StateController {
final long nowElapsed = sElapsedRealtimeClock.millis();
updateThresholdAlarmLocked(userId, pkgName, now, nowElapsed);
for (int i = 0; i < mPrefetchChangedListeners.size(); i++) {
- mPrefetchChangedListeners.valueAt(i).onPrefetchCacheUpdated(jobs,
- userId, pkgName, prevEstimatedLaunchTime, newEstimatedLaunchTime);
+ mPrefetchChangedListeners.valueAt(i).onPrefetchCacheUpdated(
+ jobs, userId, pkgName, prevEstimatedLaunchTime,
+ newEstimatedLaunchTime, nowElapsed);
}
if (maybeUpdateConstraintForPkgLocked(now, nowElapsed, userId, pkgName)) {
mStateChangedListener.onControllerStateChanged(jobs);
diff --git a/core/api/current.txt b/core/api/current.txt
index 3efe2ef5baea..e0433399f374 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -51979,6 +51979,7 @@ package android.view.accessibility {
method public boolean isTextEntryKey();
method public boolean isTextSelectable();
method public boolean isVisibleToUser();
+ method public void makeQueryableFromAppProcess(@NonNull android.view.View);
method @Deprecated public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
method @Deprecated public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
method @Deprecated public static android.view.accessibility.AccessibilityNodeInfo obtain();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index be84032df9a4..a0cc4f0d6775 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11479,6 +11479,7 @@ package android.service.notification {
method public void onPanelRevealed(int);
method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
method public final void unsnoozeNotification(@NonNull String);
+ field public static final String ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS = "android.service.notification.action.NOTIFICATION_ASSISTANT_DETAIL_SETTINGS";
field public static final String FEEDBACK_RATING = "feedback.rating";
field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
field public static final int SOURCE_FROM_APP = 0; // 0x0
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2a5916dfb6a8..d6b90a2792a9 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1906,6 +1906,7 @@ public class AppOpsManager {
OP_SCHEDULE_EXACT_ALARM,
OP_MANAGE_MEDIA,
OP_TURN_SCREEN_ON,
+ OP_GET_USAGE_STATS,
};
static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 7092e43596ec..7247ef77afb4 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -29,6 +29,7 @@ import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.CryptoObject;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.os.Binder;
@@ -674,6 +675,45 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
/**
+ * Forwards BiometricStateListener to FaceService.
+ *
+ * @param listener new BiometricStateListener being added
+ * @hide
+ */
+ public void registerBiometricStateListener(@NonNull BiometricStateListener listener) {
+ try {
+ mService.registerBiometricStateListener(listener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Adds a callback that gets called when the service registers all of the face
+ * authenticators (HALs).
+ *
+ * If the face authenticators are already registered when the callback is added, the
+ * callback is invoked immediately.
+ *
+ * The callback is automatically removed after it's invoked.
+ *
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public void addAuthenticatorsRegisteredCallback(
+ IFaceAuthenticatorsRegisteredCallback callback) {
+ if (mService != null) {
+ try {
+ mService.addAuthenticatorsRegisteredCallback(callback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ } else {
+ Slog.w(TAG, "addAuthenticatorsRegisteredCallback(): Service not connected!");
+ }
+ }
+
+ /**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
diff --git a/core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl b/core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl
new file mode 100644
index 000000000000..78f978d21ed7
--- /dev/null
+++ b/core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.face;
+
+import android.hardware.face.FaceSensorPropertiesInternal;
+import java.util.List;
+
+/**
+ * Callback to notify FaceManager that FaceService has registered all of the
+ * face authenticators (HALs).
+ * See {@link android.hardware.face.IFaceService#registerAuthenticators}.
+ *
+ * @hide
+ */
+oneway interface IFaceAuthenticatorsRegisteredCallback {
+ /**
+ * Notifies FaceManager that all of the face authenticators have been registered.
+ *
+ * @param sensors A consolidated list of sensor properties for all of the authenticators.
+ */
+ void onAllAuthenticatorsRegistered(in List<FaceSensorPropertiesInternal> sensors);
+}
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 369248edd580..9b56f43a0f22 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -17,9 +17,11 @@ package android.hardware.face;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricStateListener;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
import android.hardware.face.FaceSensorPropertiesInternal;
@@ -163,4 +165,11 @@ interface IFaceService {
// hidlSensors must be non-null and empty. See AuthService.java
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
void registerAuthenticators(in List<FaceSensorPropertiesInternal> hidlSensors);
+
+ // Adds a callback which gets called when the service registers all of the face
+ // authenticators. The callback is automatically removed after it's invoked.
+ void addAuthenticatorsRegisteredCallback(IFaceAuthenticatorsRegisteredCallback callback);
+
+ // Registers BiometricStateListener.
+ void registerBiometricStateListener(IBiometricStateListener listener);
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index cc7ed183ed64..1ba9a0471c88 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -202,8 +202,10 @@ interface IFingerprintService {
void setSidefpsController(in ISidefpsController controller);
// Registers BiometricStateListener.
+ @EnforcePermission("USE_BIOMETRIC_INTERNAL")
void registerBiometricStateListener(IBiometricStateListener listener);
// Sends a power button pressed event to all listeners.
+ @EnforcePermission("USE_BIOMETRIC_INTERNAL")
oneway void onPowerPressed();
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 26600e256ca1..9d05cec06d01 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2317,6 +2317,11 @@ public abstract class BatteryStats {
public abstract void finishIteratingHistoryLocked();
/**
+ * Return the base time offset for the battery history.
+ */
+ public abstract long getHistoryBaseTime();
+
+ /**
* Returns the number of times the device has been started.
*/
public abstract int getStartCount();
@@ -7601,6 +7606,8 @@ public abstract class BatteryStats {
CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
getEndPlatformVersion());
+ long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+
if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) {
if (startIteratingHistoryLocked()) {
try {
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 91042bfa3402..a38ef9676072 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -91,6 +91,21 @@ public abstract class NotificationAssistantService extends NotificationListenerS
= "android.service.notification.NotificationAssistantService";
/**
+ * Activity Action: Show notification assistant detail setting page in NAS app.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS =
+ "android.service.notification.action.NOTIFICATION_ASSISTANT_DETAIL_SETTINGS";
+
+
+ /**
* Data type: int, the feedback rating score provided by user. The score can be any integer
* value depends on the experimental and feedback UX design.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9091b7955616..59bc061f54aa 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -173,6 +173,7 @@ import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
import android.view.accessibility.AccessibilityManager.HighTextContrastChangeListener;
@@ -5318,6 +5319,7 @@ public final class ViewRootImpl implements ViewParent,
}
mAccessibilityInteractionConnectionManager.ensureNoConnection();
+ mAccessibilityInteractionConnectionManager.ensureNoDirectConnection();
removeSendWindowContentChangedCallback();
destroyHardwareRenderer();
@@ -9570,6 +9572,14 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ /**
+ * Return the connection ID for the {@link AccessibilityInteractionController} of this instance.
+ * @see AccessibilityNodeInfo#makeQueryableFromAppProcess(View)
+ */
+ public int getDirectAccessibilityConnectionId() {
+ return mAccessibilityInteractionConnectionManager.ensureDirectConnection();
+ }
+
@Override
public boolean showContextMenuForChild(View originalView) {
return false;
@@ -10445,6 +10455,8 @@ public final class ViewRootImpl implements ViewParent,
*/
final class AccessibilityInteractionConnectionManager
implements AccessibilityStateChangeListener {
+ private int mDirectConnectionId = AccessibilityNodeInfo.UNDEFINED_CONNECTION_ID;
+
@Override
public void onAccessibilityStateChanged(boolean enabled) {
if (enabled) {
@@ -10488,6 +10500,21 @@ public final class ViewRootImpl implements ViewParent,
mAccessibilityManager.removeAccessibilityInteractionConnection(mWindow);
}
}
+
+ public int ensureDirectConnection() {
+ if (mDirectConnectionId == AccessibilityNodeInfo.UNDEFINED_CONNECTION_ID) {
+ mDirectConnectionId = AccessibilityInteractionClient.addDirectConnection(
+ new AccessibilityInteractionConnection(ViewRootImpl.this));
+ }
+ return mDirectConnectionId;
+ }
+
+ public void ensureNoDirectConnection() {
+ if (mDirectConnectionId != AccessibilityNodeInfo.UNDEFINED_CONNECTION_ID) {
+ AccessibilityInteractionClient.removeConnection(mDirectConnectionId);
+ mDirectConnectionId = AccessibilityNodeInfo.UNDEFINED_CONNECTION_ID;
+ }
+ }
}
final class HighContrastTextManager implements HighTextContrastChangeListener {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 68532781f08b..227a8ef6fd60 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -114,6 +114,10 @@ public final class AccessibilityInteractionClient
private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
new SparseArray<>();
+ // Used to generate connection ids for direct app-process connections. Start sufficiently far
+ // enough from the connection ids generated by AccessibilityManagerService.
+ private static int sDirectConnectionIdCounter = 1 << 30;
+
/** List of timestamps which indicate the latest time an a11y service receives a scroll event
from a window, mapping from windowId -> timestamp. */
private static final SparseLongArray sScrollingWindows = new SparseLongArray();
@@ -232,6 +236,12 @@ public final class AccessibilityInteractionClient
return;
}
synchronized (sConnectionCache) {
+ IAccessibilityServiceConnection existingConnection = getConnection(connectionId);
+ if (existingConnection instanceof DirectAccessibilityConnection) {
+ throw new IllegalArgumentException(
+ "Cannot add service connection with id " + connectionId
+ + " which conflicts with existing direct connection.");
+ }
sConnectionCache.put(connectionId, connection);
if (!initializeCache) {
return;
@@ -242,6 +252,33 @@ public final class AccessibilityInteractionClient
}
/**
+ * Adds a new {@link DirectAccessibilityConnection} using the provided
+ * {@link IAccessibilityInteractionConnection} to create a direct connection between
+ * this client and the {@link android.view.ViewRootImpl} for queries inside the app process.
+ *
+ * <p>
+ * See {@link DirectAccessibilityConnection} for supported methods.
+ * </p>
+ *
+ * @param connection The ViewRootImpl's {@link IAccessibilityInteractionConnection}.
+ */
+ public static int addDirectConnection(IAccessibilityInteractionConnection connection) {
+ synchronized (sConnectionCache) {
+ int connectionId = sDirectConnectionIdCounter++;
+ if (getConnection(connectionId) != null) {
+ throw new IllegalArgumentException(
+ "Cannot add direct connection with existing id " + connectionId);
+ }
+ DirectAccessibilityConnection directAccessibilityConnection =
+ new DirectAccessibilityConnection(connection);
+ sConnectionCache.put(connectionId, directAccessibilityConnection);
+ // Do not use AccessibilityCache for this connection, since there is no corresponding
+ // AccessibilityService to handle cache invalidation events.
+ return connectionId;
+ }
+ }
+
+ /**
* Gets a cached associated with the connection id if available.
*
*/
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 953f2615b539..5d527500ff7b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -58,6 +58,7 @@ import android.view.SurfaceView;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import android.widget.TextView;
import com.android.internal.R;
@@ -82,7 +83,9 @@ import java.util.Objects;
* </p>
* <p>
* Once an accessibility node info is delivered to an accessibility service it is
- * made immutable and calling a state mutation method generates an error.
+ * made immutable and calling a state mutation method generates an error. See
+ * {@link #makeQueryableFromAppProcess(View)} if you would like to inspect the
+ * node tree from the app process for testing or debugging tools.
* </p>
* <p>
* Please refer to {@link android.accessibilityservice.AccessibilityService} for
@@ -1156,8 +1159,8 @@ public class AccessibilityNodeInfo implements Parcelable {
* @param index The child index.
* @return The child node.
*
- * @throws IllegalStateException If called outside of an AccessibilityService.
- *
+ * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before
+ * calling {@link #makeQueryableFromAppProcess(View)}.
*/
public AccessibilityNodeInfo getChild(int index) {
return getChild(index, FLAG_PREFETCH_DESCENDANTS_HYBRID);
@@ -1171,7 +1174,8 @@ public class AccessibilityNodeInfo implements Parcelable {
* @param prefetchingStrategy the prefetching strategy.
* @return The child node.
*
- * @throws IllegalStateException If called outside of an AccessibilityService.
+ * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before
+ * calling {@link #makeQueryableFromAppProcess(View)}.
*
* @see AccessibilityNodeInfo#getParent(int) for a description of prefetching.
*/
@@ -1893,6 +1897,9 @@ public class AccessibilityNodeInfo implements Parcelable {
* Gets the parent.
*
* @return The parent.
+ *
+ * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before
+ * calling {@link #makeQueryableFromAppProcess(View)}.
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
@@ -1920,7 +1927,8 @@ public class AccessibilityNodeInfo implements Parcelable {
* @param prefetchingStrategy the prefetching strategy.
* @return The parent.
*
- * @throws IllegalStateException If called outside of an AccessibilityService.
+ * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before
+ * calling {@link #makeQueryableFromAppProcess(View)}.
*
* @see #FLAG_PREFETCH_ANCESTORS
* @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST
@@ -3642,6 +3650,47 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Connects this node to the View's root so that operations on this node can query the entire
+ * {@link AccessibilityNodeInfo} tree and perform accessibility actions on nodes.
+ *
+ * <p>
+ * This is intended for short-lived inspections from testing or debugging tools in the app
+ * process. After calling this method, all nodes linked to this node (children, ancestors, etc.)
+ * are also queryable. Operations on this node tree will only succeed as long as the associated
+ * view hierarchy remains attached to a window.
+ * </p>
+ *
+ * <p>
+ * Calling this method more than once on the same node is a no-op; if you wish to inspect a
+ * different view hierarchy then create a new node from any view in that hierarchy and call this
+ * method on that node.
+ * </p>
+ *
+ * <p>
+ * Testing or debugging tools should create this {@link AccessibilityNodeInfo} node using
+ * {@link View#createAccessibilityNodeInfo()} or {@link AccessibilityNodeProvider} and call this
+ * method, then navigate and interact with the node tree by calling methods on the node.
+ * </p>
+ *
+ * @param view The view that generated this node, or any view in the same view-root hierarchy.
+ * @throws IllegalStateException If called from an {@link AccessibilityService}, or if provided
+ * a {@link View} that is not attached to a window.
+ */
+ public void makeQueryableFromAppProcess(@NonNull View view) {
+ enforceNotSealed();
+ if (mConnectionId != UNDEFINED_CONNECTION_ID) {
+ return;
+ }
+
+ ViewRootImpl viewRootImpl = view.getViewRootImpl();
+ if (viewRootImpl == null) {
+ throw new IllegalStateException(
+ "Cannot link a node to a view that is not attached to a window.");
+ }
+ setConnectionId(viewRootImpl.getDirectAccessibilityConnectionId());
+ }
+
+ /**
* Sets if this instance is sealed.
*
* @param sealed Whether is sealed.
@@ -3665,15 +3714,21 @@ public class AccessibilityNodeInfo implements Parcelable {
return mSealed;
}
+ private static boolean usingDirectConnection(int connectionId) {
+ return AccessibilityInteractionClient.getConnection(
+ connectionId) instanceof DirectAccessibilityConnection;
+ }
+
/**
- * Enforces that this instance is sealed.
+ * Enforces that this instance is sealed, unless using a {@link DirectAccessibilityConnection}
+ * which allows queries while the node is not sealed.
*
* @throws IllegalStateException If this instance is not sealed.
*
* @hide
*/
protected void enforceSealed() {
- if (!isSealed()) {
+ if (!usingDirectConnection(mConnectionId) && !isSealed()) {
throw new IllegalStateException("Cannot perform this "
+ "action on a not sealed instance.");
}
@@ -4499,7 +4554,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private static boolean canPerformRequestOverConnection(int connectionId,
int windowId, long accessibilityNodeId) {
- return ((windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
+ final boolean hasWindowId = windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ return ((usingDirectConnection(connectionId) || hasWindowId)
&& (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
&& (connectionId != UNDEFINED_CONNECTION_ID));
}
diff --git a/core/java/android/view/accessibility/DirectAccessibilityConnection.java b/core/java/android/view/accessibility/DirectAccessibilityConnection.java
new file mode 100644
index 000000000000..71746ee5dbab
--- /dev/null
+++ b/core/java/android/view/accessibility/DirectAccessibilityConnection.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.graphics.Matrix;
+import android.graphics.Region;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.view.MagnificationSpec;
+
+/**
+ * Minimal {@link IAccessibilityServiceConnection} implementation that interacts
+ * with the {@link android.view.AccessibilityInteractionController} of a
+ * {@link android.view.ViewRootImpl}.
+ *
+ * <p>
+ * Uses {@link android.view.ViewRootImpl}'s {@link IAccessibilityServiceConnection} that wraps
+ * {@link android.view.AccessibilityInteractionController} within the app process, so that no
+ * interprocess communication is performed.
+ * </p>
+ *
+ * <p>
+ * Only the following methods are supported:
+ * <li>{@link #findAccessibilityNodeInfoByAccessibilityId}</li>
+ * <li>{@link #findAccessibilityNodeInfosByText}</li>
+ * <li>{@link #findAccessibilityNodeInfosByViewId}</li>
+ * <li>{@link #findFocus}</li>
+ * <li>{@link #focusSearch}</li>
+ * <li>{@link #performAccessibilityAction}</li>
+ * </p>
+ *
+ * <p>
+ * Other methods are no-ops and return default values.
+ * </p>
+ */
+class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Default {
+ private final IAccessibilityInteractionConnection mAccessibilityInteractionConnection;
+
+ // Fetch all views, but do not use prefetching/cache since this "connection" does not
+ // receive cache invalidation events (as it is not linked to an AccessibilityService).
+ private static final int FETCH_FLAGS =
+ AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS
+ | AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ private static final MagnificationSpec MAGNIFICATION_SPEC = new MagnificationSpec();
+ private static final int PID = Process.myPid();
+ private static final Region INTERACTIVE_REGION = null;
+ private static final float[] TRANSFORM_MATRIX = new float[9];
+
+ static {
+ Matrix.IDENTITY_MATRIX.getValues(TRANSFORM_MATRIX);
+ }
+
+ DirectAccessibilityConnection(
+ IAccessibilityInteractionConnection accessibilityInteractionConnection) {
+ mAccessibilityInteractionConnection = accessibilityInteractionConnection;
+ }
+
+ @Override
+ public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+ long accessibilityNodeId, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
+ Bundle arguments) throws RemoteException {
+ mAccessibilityInteractionConnection.findAccessibilityNodeInfoByAccessibilityId(
+ accessibilityNodeId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID,
+ threadId, MAGNIFICATION_SPEC, TRANSFORM_MATRIX, arguments);
+ return new String[0];
+ }
+
+ @Override
+ public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
+ long accessibilityNodeId, String text, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, long threadId)
+ throws RemoteException {
+ mAccessibilityInteractionConnection.findAccessibilityNodeInfosByText(accessibilityNodeId,
+ text, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
+ MAGNIFICATION_SPEC, TRANSFORM_MATRIX);
+ return new String[0];
+ }
+
+ @Override
+ public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+ long accessibilityNodeId, String viewId, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, long threadId)
+ throws RemoteException {
+ mAccessibilityInteractionConnection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
+ viewId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
+ MAGNIFICATION_SPEC, TRANSFORM_MATRIX);
+ return new String[0];
+ }
+
+ @Override
+ public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)
+ throws RemoteException {
+ mAccessibilityInteractionConnection.findFocus(accessibilityNodeId, focusType,
+ INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
+ MAGNIFICATION_SPEC, TRANSFORM_MATRIX);
+ return new String[0];
+ }
+
+ @Override
+ public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)
+ throws RemoteException {
+ mAccessibilityInteractionConnection.focusSearch(accessibilityNodeId, direction,
+ INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
+ MAGNIFICATION_SPEC, TRANSFORM_MATRIX);
+ return new String[0];
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
+ int action, Bundle arguments, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, long threadId)
+ throws RemoteException {
+ mAccessibilityInteractionConnection.performAccessibilityAction(accessibilityNodeId, action,
+ arguments, interactionId, callback, FETCH_FLAGS, PID, threadId);
+ return true;
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 6909965edcd8..962870e733f7 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -17,35 +17,25 @@
package com.android.internal.os;
import android.annotation.Nullable;
-import android.os.BatteryManager;
-import android.os.BatteryStats.HistoryItem;
-import android.os.BatteryStats.HistoryStepDetails;
-import android.os.BatteryStats.HistoryTag;
+import android.os.BatteryStats;
import android.os.Parcel;
-import android.os.ParcelFormatException;
-import android.os.Process;
import android.os.StatFs;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
-import android.util.SparseArray;
-import android.util.TimeUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ParseUtils;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Supplier;
/**
* BatteryStatsHistory encapsulates battery history files.
@@ -66,62 +56,57 @@ import java.util.concurrent.locks.ReentrantLock;
* All interfaces in BatteryStatsHistory should only be called by BatteryStatsImpl and protected by
* locks on BatteryStatsImpl object.
*/
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class BatteryStatsHistory {
private static final boolean DEBUG = false;
private static final String TAG = "BatteryStatsHistory";
// Current on-disk Parcel version. Must be updated when the format of the parcelable changes
- private static final int VERSION = 208;
+ public static final int VERSION = 208;
- private static final String HISTORY_DIR = "battery-history";
- private static final String FILE_SUFFIX = ".bin";
+ public static final String HISTORY_DIR = "battery-history";
+ public static final String FILE_SUFFIX = ".bin";
private static final int MIN_FREE_SPACE = 100 * 1024 * 1024;
-
// Part of initial delta int that specifies the time delta.
- static final int DELTA_TIME_MASK = 0x7ffff;
- static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long
- static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int
- static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update.
+ public static final int DELTA_TIME_MASK = 0x7ffff;
+ public static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long
+ public static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int
+ public static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update.
// Flag in delta int: a new battery level int follows.
- static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
+ public static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
// Flag in delta int: a new full state and battery status int follows.
- static final int DELTA_STATE_FLAG = 0x00100000;
+ public static final int DELTA_STATE_FLAG = 0x00100000;
// Flag in delta int: a new full state2 int follows.
- static final int DELTA_STATE2_FLAG = 0x00200000;
+ public static final int DELTA_STATE2_FLAG = 0x00200000;
// Flag in delta int: contains a wakelock or wakeReason tag.
- static final int DELTA_WAKELOCK_FLAG = 0x00400000;
+ public static final int DELTA_WAKELOCK_FLAG = 0x00400000;
// Flag in delta int: contains an event description.
- static final int DELTA_EVENT_FLAG = 0x00800000;
+ public static final int DELTA_EVENT_FLAG = 0x00800000;
// Flag in delta int: contains the battery charge count in uAh.
- static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
+ public static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
// These upper bits are the frequently changing state bits.
- static final int DELTA_STATE_MASK = 0xfe000000;
+ public static final int DELTA_STATE_MASK = 0xfe000000;
// These are the pieces of battery state that are packed in to the upper bits of
// the state int that have been packed in to the first delta int. They must fit
// in STATE_BATTERY_MASK.
- static final int STATE_BATTERY_MASK = 0xff000000;
- static final int STATE_BATTERY_STATUS_MASK = 0x00000007;
- static final int STATE_BATTERY_STATUS_SHIFT = 29;
- static final int STATE_BATTERY_HEALTH_MASK = 0x00000007;
- static final int STATE_BATTERY_HEALTH_SHIFT = 26;
- static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
- static final int STATE_BATTERY_PLUG_SHIFT = 24;
+ public static final int STATE_BATTERY_MASK = 0xff000000;
+ public static final int STATE_BATTERY_STATUS_MASK = 0x00000007;
+ public static final int STATE_BATTERY_STATUS_SHIFT = 29;
+ public static final int STATE_BATTERY_HEALTH_MASK = 0x00000007;
+ public static final int STATE_BATTERY_HEALTH_SHIFT = 26;
+ public static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
+ public static final int STATE_BATTERY_PLUG_SHIFT = 24;
// We use the low bit of the battery state int to indicate that we have full details
// from a battery level change.
- static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+ public static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
// Flag in history tag index: indicates that this is the first occurrence of this tag,
// therefore the tag value is written in the parcel
- static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
+ public static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
+ @Nullable
+ private final Supplier<Integer> mMaxHistoryFiles;
private final Parcel mHistoryBuffer;
- private final File mSystemDir;
- private final HistoryStepDetailsCalculator mStepDetailsCalculator;
private final File mHistoryDir;
- private final Clock mClock;
-
- private int mMaxHistoryFiles;
- private int mMaxHistoryBufferSize;
-
/**
* The active history file that the history buffer is backed up into.
*/
@@ -159,77 +144,19 @@ public class BatteryStatsHistory {
*/
private int mParcelIndex = 0;
- private final ReentrantLock mWriteLock = new ReentrantLock();
-
- private final HistoryItem mHistoryCur = new HistoryItem();
-
- private boolean mHaveBatteryLevel;
- private boolean mRecordingHistory;
-
- private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
- private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024;
-
- private final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
- private SparseArray<HistoryTag> mHistoryTags;
- private final HistoryItem mHistoryLastWritten = new HistoryItem();
- private final HistoryItem mHistoryLastLastWritten = new HistoryItem();
- private final HistoryItem mHistoryAddTmp = new HistoryItem();
- private int mNextHistoryTagIdx = 0;
- private int mNumHistoryTagChars = 0;
- private int mHistoryBufferLastPos = -1;
- private int mActiveHistoryStates = 0xffffffff;
- private int mActiveHistoryStates2 = 0xffffffff;
- private long mLastHistoryElapsedRealtimeMs = 0;
- private long mTrackRunningHistoryElapsedRealtimeMs = 0;
- private long mTrackRunningHistoryUptimeMs = 0;
- private long mHistoryBaseTimeMs;
-
- private byte mLastHistoryStepLevel = 0;
-
- private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
-
- /**
- * A delegate responsible for computing additional details for a step in battery history.
- */
- public interface HistoryStepDetailsCalculator {
- /**
- * Returns additional details for the current history step or null.
- */
- @Nullable
- HistoryStepDetails getHistoryStepDetails();
-
- /**
- * Resets the calculator to get ready for a new battery session
- */
- void clear();
- }
-
/**
* Constructor
*
- * @param systemDir typically /data/system
- * @param maxHistoryFiles the largest number of history buffer files to keep
- * @param maxHistoryBufferSize the most amount of RAM to used for buffering of history steps
+ * @param historyBuffer The in-memory history buffer.
+ * @param systemDir typically /data/system
+ * @param maxHistoryFiles the largest number of history buffer files to keep
*/
- public BatteryStatsHistory(File systemDir, int maxHistoryFiles, int maxHistoryBufferSize,
- HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
- this(Parcel.obtain(), systemDir, maxHistoryFiles, maxHistoryBufferSize,
- stepDetailsCalculator, clock);
- initHistoryBuffer();
- }
-
- @VisibleForTesting
public BatteryStatsHistory(Parcel historyBuffer, File systemDir,
- int maxHistoryFiles, int maxHistoryBufferSize,
- HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ Supplier<Integer> maxHistoryFiles) {
mHistoryBuffer = historyBuffer;
- mSystemDir = systemDir;
+ mHistoryDir = new File(systemDir, HISTORY_DIR);
mMaxHistoryFiles = maxHistoryFiles;
- mMaxHistoryBufferSize = maxHistoryBufferSize;
- mStepDetailsCalculator = stepDetailsCalculator;
- mClock = clock;
- mHistoryDir = new File(systemDir, HISTORY_DIR);
mHistoryDir.mkdirs();
if (!mHistoryDir.exists()) {
Slog.wtf(TAG, "HistoryDir does not exist:" + mHistoryDir.getPath());
@@ -265,81 +192,19 @@ public class BatteryStatsHistory {
}
}
- public BatteryStatsHistory(HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
- mStepDetailsCalculator = stepDetailsCalculator;
- mClock = clock;
-
- mHistoryBuffer = Parcel.obtain();
- mSystemDir = null;
- mHistoryDir = null;
- initHistoryBuffer();
- }
-
/**
* Used when BatteryStatsImpl object is created from deserialization of a parcel,
- * such as a checkin file.
+ * such as Settings app or checkin file.
+ * @param historyBuffer the history buffer
*/
- private BatteryStatsHistory(Parcel historyBuffer,
- HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
- mHistoryBuffer = historyBuffer;
- mClock = clock;
- mSystemDir = null;
+ public BatteryStatsHistory(Parcel historyBuffer) {
mHistoryDir = null;
- mStepDetailsCalculator = stepDetailsCalculator;
- }
-
- private void initHistoryBuffer() {
- mHistoryBaseTimeMs = 0;
- mLastHistoryElapsedRealtimeMs = 0;
- mTrackRunningHistoryElapsedRealtimeMs = 0;
- mTrackRunningHistoryUptimeMs = 0;
-
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
- mHistoryBuffer.setDataCapacity(mMaxHistoryBufferSize / 2);
- mHistoryLastLastWritten.clear();
- mHistoryLastWritten.clear();
- mHistoryTagPool.clear();
- mNextHistoryTagIdx = 0;
- mNumHistoryTagChars = 0;
- mHistoryBufferLastPos = -1;
- mActiveHistoryStates = 0xffffffff;
- mActiveHistoryStates2 = 0xffffffff;
- if (mStepDetailsCalculator != null) {
- mStepDetailsCalculator.clear();
- }
- }
-
- /**
- * Changes the maximum number of history files to be kept.
- */
- public void setMaxHistoryFiles(int maxHistoryFiles) {
- mMaxHistoryFiles = maxHistoryFiles;
- }
-
- /**
- * Changes the maximum size of the history buffer, in bytes.
- */
- public void setMaxHistoryBufferSize(int maxHistoryBufferSize) {
- mMaxHistoryBufferSize = maxHistoryBufferSize;
- }
-
- /**
- * Creates a read-only copy of the battery history. Does not copy the files stored
- * in the system directory, so it is not safe while actively writing history.
- */
- public BatteryStatsHistory copy() {
- // Make a copy of battery history to avoid concurrent modification.
- Parcel historyBuffer = Parcel.obtain();
- historyBuffer.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
- return new BatteryStatsHistory(historyBuffer, mSystemDir, 0, 0, null, null);
+ mHistoryBuffer = historyBuffer;
+ mMaxHistoryFiles = null;
}
- /**
- * Returns true if this instance only supports reading history.
- */
- public boolean isReadOnly() {
- return mActiveFile == null;
+ public File getHistoryDirectory() {
+ return mHistoryDir;
}
/**
@@ -356,13 +221,12 @@ public class BatteryStatsHistory {
/**
* Create history AtomicFile from file number.
- *
* @param num file number.
* @return AtomicFile object.
*/
private AtomicFile getFile(int num) {
return new AtomicFile(
- new File(mHistoryDir, num + FILE_SUFFIX));
+ new File(mHistoryDir, num + FILE_SUFFIX));
}
/**
@@ -370,7 +234,7 @@ public class BatteryStatsHistory {
* create next history file.
*/
public void startNextFile() {
- if (mMaxHistoryFiles == 0) {
+ if (mMaxHistoryFiles == null) {
Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history");
return;
}
@@ -400,7 +264,7 @@ public class BatteryStatsHistory {
// if there are more history files than allowed, delete oldest history files.
// mMaxHistoryFiles comes from Constants.MAX_HISTORY_FILES and can be updated by GService
// config at run time.
- while (mFileNumbers.size() > mMaxHistoryFiles) {
+ while (mFileNumbers.size() > mMaxHistoryFiles.get()) {
int oldest = mFileNumbers.get(0);
getFile(oldest).delete();
mFileNumbers.remove(0);
@@ -408,43 +272,36 @@ public class BatteryStatsHistory {
}
/**
- * Clear history buffer and delete all existing history files. Active history file start from
- * number 0 again.
+ * Delete all existing history files. Active history file start from number 0 again.
*/
- public void reset() {
- if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!");
+ public void resetAllFiles() {
for (Integer i : mFileNumbers) {
getFile(i).delete();
}
mFileNumbers.clear();
mFileNumbers.add(0);
setActiveFile(0);
-
- initHistoryBuffer();
}
/**
* Start iterating history files and history buffer.
- *
* @return always return true.
*/
- public BatteryStatsHistoryIterator iterate() {
+ public boolean startIteratingHistory() {
mRecordCount = 0;
mCurrentFileIndex = 0;
mCurrentParcel = null;
mCurrentParcelEnd = 0;
mParcelIndex = 0;
- mBatteryStatsHistoryIterator = new BatteryStatsHistoryIterator(this);
- return mBatteryStatsHistoryIterator;
+ return true;
}
/**
* Finish iterating history files and history buffer.
*/
- void finishIteratingHistory() {
+ public void finishIteratingHistory() {
// setDataPosition so mHistoryBuffer Parcel can be written.
mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
- mBatteryStatsHistoryIterator = null;
if (DEBUG) {
Slog.d(TAG, "Battery history records iterated: " + mRecordCount);
}
@@ -454,12 +311,11 @@ public class BatteryStatsHistory {
* When iterating history files and history buffer, always start from the lowest numbered
* history file, when reached the mActiveFile (highest numbered history file), do not read from
* mActiveFile, read from history buffer instead because the buffer has more updated data.
- *
* @param out a history item.
* @return The parcel that has next record. null if finished all history files and history
- * buffer
+ * buffer
*/
- public Parcel getNextParcel(HistoryItem out) {
+ public Parcel getNextParcel(BatteryStats.HistoryItem out) {
if (mRecordCount == 0) {
// reset out if it is the first record.
out.clear();
@@ -467,7 +323,8 @@ public class BatteryStatsHistory {
++mRecordCount;
// First iterate through all records in current parcel.
- if (mCurrentParcel != null) {
+ if (mCurrentParcel != null)
+ {
if (mCurrentParcel.dataPosition() < mCurrentParcelEnd) {
// There are more records in current parcel.
return mCurrentParcel;
@@ -532,8 +389,7 @@ public class BatteryStatsHistory {
/**
* Read history file into a parcel.
- *
- * @param out the Parcel read into.
+ * @param out the Parcel read into.
* @param file the File to read from.
* @return true if success, false otherwise.
*/
@@ -546,8 +402,8 @@ public class BatteryStatsHistory {
Slog.d(TAG, "readFileToParcel:" + file.getBaseFile().getPath()
+ " duration ms:" + (SystemClock.uptimeMillis() - start));
}
- } catch (Exception e) {
- Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e);
+ } catch(Exception e) {
+ Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
return false;
}
out.unmarshall(raw, 0, raw.length);
@@ -557,7 +413,6 @@ public class BatteryStatsHistory {
/**
* Skip the header part of history parcel.
- *
* @param p history parcel to skip head.
* @return true if version match, false if not.
*/
@@ -573,68 +428,18 @@ public class BatteryStatsHistory {
}
/**
- * Writes the battery history contents for persistence.
- */
- public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
- out.writeBoolean(inclHistory);
- if (inclHistory) {
- writeToParcel(out);
- }
-
- out.writeInt(mHistoryTagPool.size());
- for (Map.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
- HistoryTag tag = ent.getKey();
- out.writeInt(ent.getValue());
- out.writeString(tag.string);
- out.writeInt(tag.uid);
- }
- }
-
- /**
- * Reads battery history contents from a persisted parcel.
- */
- public void readSummaryFromParcel(Parcel in) {
- boolean inclHistory = in.readBoolean();
- if (inclHistory) {
- readFromParcel(in);
- }
-
- mHistoryTagPool.clear();
- mNextHistoryTagIdx = 0;
- mNumHistoryTagChars = 0;
-
- int numTags = in.readInt();
- for (int i = 0; i < numTags; i++) {
- int idx = in.readInt();
- String str = in.readString();
- int uid = in.readInt();
- HistoryTag tag = new HistoryTag();
- tag.string = str;
- tag.uid = uid;
- tag.poolIdx = idx;
- mHistoryTagPool.put(tag, idx);
- if (idx >= mNextHistoryTagIdx) {
- mNextHistoryTagIdx = idx + 1;
- }
- mNumHistoryTagChars += tag.string.length() + 1;
- }
- }
-
- /**
* Read all history files and serialize into a big Parcel.
* Checkin file calls this method.
*
* @param out the output parcel
*/
public void writeToParcel(Parcel out) {
- writeHistoryBuffer(out);
writeToParcel(out, false /* useBlobs */);
}
/**
* This is for Settings app, when Settings app receives big history parcel, it call
* this method to parse it into list of parcels.
- *
* @param out the output parcel
*/
public void writeToBatteryUsageStatsParcel(Parcel out) {
@@ -645,13 +450,13 @@ public class BatteryStatsHistory {
private void writeToParcel(Parcel out, boolean useBlobs) {
final long start = SystemClock.uptimeMillis();
out.writeInt(mFileNumbers.size() - 1);
- for (int i = 0; i < mFileNumbers.size() - 1; i++) {
+ for(int i = 0; i < mFileNumbers.size() - 1; i++) {
AtomicFile file = getFile(mFileNumbers.get(i));
byte[] raw = new byte[0];
try {
raw = file.readFully();
- } catch (Exception e) {
- Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e);
+ } catch(Exception e) {
+ Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
}
if (useBlobs) {
out.writeBlob(raw);
@@ -675,55 +480,17 @@ public class BatteryStatsHistory {
Parcel historyBuffer = Parcel.obtain();
historyBuffer.unmarshall(historyBlob, 0, historyBlob.length);
- BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer, null,
- Clock.SYSTEM_CLOCK);
+ BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer);
history.readFromParcel(in, true /* useBlobs */);
return history;
}
/**
- * Read history from a check-in file.
- */
- public boolean readSummary() {
- if (mActiveFile == null) {
- Slog.w(TAG, "readSummary: no history file associated with this instance");
- return false;
- }
-
- Parcel parcel = Parcel.obtain();
- try {
- final long start = SystemClock.uptimeMillis();
- if (mActiveFile.exists()) {
- byte[] raw = mActiveFile.readFully();
- if (raw.length > 0) {
- parcel.unmarshall(raw, 0, raw.length);
- parcel.setDataPosition(0);
- readHistoryBuffer(parcel);
- }
- if (DEBUG) {
- Slog.d(TAG, "read history file::"
- + mActiveFile.getBaseFile().getPath()
- + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
- - start));
- }
- }
- } catch (Exception e) {
- Slog.e(TAG, "Error reading battery history", e);
- reset();
- return false;
- } finally {
- parcel.recycle();
- }
- return true;
- }
-
- /**
* This is for the check-in file, which has all history files embedded.
*
* @param in the input parcel.
*/
public void readFromParcel(Parcel in) {
- readHistoryBuffer(in);
readFromParcel(in, false /* useBlobs */);
}
@@ -731,7 +498,7 @@ public class BatteryStatsHistory {
final long start = SystemClock.uptimeMillis();
mHistoryParcels = new ArrayList<>();
final int count = in.readInt();
- for (int i = 0; i < count; i++) {
+ for(int i = 0; i < count; i++) {
byte[] temp = useBlobs ? in.readBlob() : in.createByteArray();
if (temp == null || temp.length == 0) {
continue;
@@ -754,12 +521,10 @@ public class BatteryStatsHistory {
return stats.getAvailableBytes() > MIN_FREE_SPACE;
}
- @VisibleForTesting
public List<Integer> getFilesNumbers() {
return mFileNumbers;
}
- @VisibleForTesting
public AtomicFile getActiveFile() {
return mActiveFile;
}
@@ -769,972 +534,15 @@ public class BatteryStatsHistory {
*/
public int getHistoryUsedSize() {
int ret = 0;
- for (int i = 0; i < mFileNumbers.size() - 1; i++) {
+ for(int i = 0; i < mFileNumbers.size() - 1; i++) {
ret += getFile(mFileNumbers.get(i)).getBaseFile().length();
}
ret += mHistoryBuffer.dataSize();
if (mHistoryParcels != null) {
- for (int i = 0; i < mHistoryParcels.size(); i++) {
+ for(int i = 0; i < mHistoryParcels.size(); i++) {
ret += mHistoryParcels.get(i).dataSize();
}
}
return ret;
}
-
- /**
- * Enables/disables recording of history. When disabled, all "record*" calls are a no-op.
- */
- public void setHistoryRecordingEnabled(boolean enabled) {
- mRecordingHistory = enabled;
- }
-
- /**
- * Returns true if history recording is enabled.
- */
- public boolean isRecordingHistory() {
- return mRecordingHistory;
- }
-
- /**
- * Forces history recording regardless of charging state.
- */
- @VisibleForTesting
- public void forceRecordAllHistory() {
- mHaveBatteryLevel = true;
- mRecordingHistory = true;
- }
-
- /**
- * Starts a history buffer by recording the current wall-clock time.
- */
- public void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
- boolean reset) {
- mRecordingHistory = true;
- mHistoryCur.currentTime = mClock.currentTimeMillis();
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
- reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME);
- mHistoryCur.currentTime = 0;
- }
-
- /**
- * Prepares to continue recording after restoring previous history from persistent storage.
- */
- public void continueRecordingHistory() {
- if (mHistoryBuffer.dataPosition() <= 0 && mFileNumbers.size() <= 1) {
- return;
- }
-
- mRecordingHistory = true;
- final long elapsedRealtimeMs = mClock.elapsedRealtime();
- final long uptimeMs = mClock.uptimeMillis();
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_START);
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
- }
-
- /**
- * Notes the current battery state to be reflected in the next written history item.
- */
- public void setBatteryState(boolean charging, int status, int level, int chargeUah) {
- mHaveBatteryLevel = true;
- setChargingState(charging);
- mHistoryCur.batteryStatus = (byte) status;
- mHistoryCur.batteryLevel = (byte) level;
- mHistoryCur.batteryChargeUah = chargeUah;
- }
-
- /**
- * Notes the current battery state to be reflected in the next written history item.
- */
- public void setBatteryState(int status, int level, int health, int plugType, int temperature,
- int voltageMv, int chargeUah) {
- mHaveBatteryLevel = true;
- mHistoryCur.batteryStatus = (byte) status;
- mHistoryCur.batteryLevel = (byte) level;
- mHistoryCur.batteryHealth = (byte) health;
- mHistoryCur.batteryPlugType = (byte) plugType;
- mHistoryCur.batteryTemperature = (short) temperature;
- mHistoryCur.batteryVoltage = (char) voltageMv;
- mHistoryCur.batteryChargeUah = chargeUah;
- }
-
- /**
- * Notes the current power plugged-in state to be reflected in the next written history item.
- */
- public void setPluggedInState(boolean pluggedIn) {
- if (pluggedIn) {
- mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- } else {
- mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- }
- }
-
- /**
- * Notes the current battery charging state to be reflected in the next written history item.
- */
- public void setChargingState(boolean charging) {
- if (charging) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
- } else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
- }
- }
-
- /**
- * Records a history event with the given code, name and UID.
- */
- public void recordEvent(long elapsedRealtimeMs, long uptimeMs, int code, String name,
- int uid) {
- mHistoryCur.eventCode = code;
- mHistoryCur.eventTag = mHistoryCur.localEventTag;
- mHistoryCur.eventTag.string = name;
- mHistoryCur.eventTag.uid = uid;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a time change event.
- */
- public void recordCurrentTimeChange(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
- if (!mRecordingHistory) {
- return;
- }
-
- mHistoryCur.currentTime = currentTimeMs;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
- HistoryItem.CMD_CURRENT_TIME);
- mHistoryCur.currentTime = 0;
- }
-
- /**
- * Records a system shutdown event.
- */
- public void recordShutdownEvent(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
- if (!mRecordingHistory) {
- return;
- }
-
- mHistoryCur.currentTime = currentTimeMs;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_SHUTDOWN);
- mHistoryCur.currentTime = 0;
- }
-
- /**
- * Records a battery state change event.
- */
- public void recordBatteryState(long elapsedRealtimeMs, long uptimeMs, int batteryLevel,
- boolean isPlugged) {
- mHistoryCur.batteryLevel = (byte) batteryLevel;
- setPluggedInState(isPlugged);
- if (DEBUG) {
- Slog.v(TAG, "Battery unplugged to: "
- + Integer.toHexString(mHistoryCur.states));
- }
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a history item with the amount of charge consumed by WiFi. Used on certain devices
- * equipped with on-device power metering.
- */
- public void recordWifiConsumedCharge(long elapsedRealtimeMs, long uptimeMs,
- double monitoredRailChargeMah) {
- mHistoryCur.wifiRailChargeMah += monitoredRailChargeMah;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a wakelock start event.
- */
- public void recordWakelockStartEvent(long elapsedRealtimeMs, long uptimeMs, String historyName,
- int uid) {
- mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName;
- mHistoryCur.wakelockTag.uid = uid;
- recordStateStartEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
- }
-
- /**
- * Updates the previous history event with a wakelock name and UID.
- */
- public boolean maybeUpdateWakelockTag(long elapsedRealtimeMs, long uptimeMs, String historyName,
- int uid) {
- if (mHistoryLastWritten.cmd != HistoryItem.CMD_UPDATE) {
- return false;
- }
- if (mHistoryLastWritten.wakelockTag != null) {
- // We'll try to update the last tag.
- mHistoryLastWritten.wakelockTag = null;
- mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName;
- mHistoryCur.wakelockTag.uid = uid;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
- return true;
- }
-
- /**
- * Records an event when some state flag changes to true.
- */
- public void recordStateStartEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states |= stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records an event when some state flag changes to false.
- */
- public void recordStateStopEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states &= ~stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records an event when some state flags change to true and some to false.
- */
- public void recordStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int stateStartFlags,
- int stateStopFlags) {
- mHistoryCur.states = (mHistoryCur.states | stateStartFlags) & ~stateStopFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records an event when some state2 flag changes to true.
- */
- public void recordState2StartEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states2 |= stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records an event when some state2 flag changes to false.
- */
- public void recordState2StopEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states2 &= ~stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records an wakeup event.
- */
- public void recordWakeupEvent(long elapsedRealtimeMs, long uptimeMs, String reason) {
- mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
- mHistoryCur.wakeReasonTag.string = reason;
- mHistoryCur.wakeReasonTag.uid = 0;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a screen brightness change event.
- */
- public void recordScreenBrightnessEvent(long elapsedRealtimeMs, long uptimeMs,
- int brightnessBin) {
- mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
- | (brightnessBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a GNSS signal level change event.
- */
- public void recordGpsSignalQualityEvent(long elapsedRealtimeMs, long uptimeMs,
- int signalLevel) {
- mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
- | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a device idle mode change event.
- */
- public void recordDeviceIdleEvent(long elapsedRealtimeMs, long uptimeMs, int mode) {
- mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
- | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a telephony state change event.
- */
- public void recordPhoneStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int addStateFlag,
- int removeStateFlag, int state, int signalStrength) {
- mHistoryCur.states = (mHistoryCur.states | addStateFlag) & ~removeStateFlag;
- if (state != -1) {
- mHistoryCur.states =
- (mHistoryCur.states & ~HistoryItem.STATE_PHONE_STATE_MASK)
- | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
- }
- if (signalStrength != -1) {
- mHistoryCur.states =
- (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
- | (signalStrength << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
- }
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a data connection type change event.
- */
- public void recordDataConnectionTypeChangeEvent(long elapsedRealtimeMs, long uptimeMs,
- int dataConnectionType) {
- mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_DATA_CONNECTION_MASK)
- | (dataConnectionType << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a WiFi supplicant state change event.
- */
- public void recordWifiSupplicantStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
- int supplState) {
- mHistoryCur.states2 =
- (mHistoryCur.states2 & ~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
- | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Records a WiFi signal strength change event.
- */
- public void recordWifiSignalStrengthChangeEvent(long elapsedRealtimeMs, long uptimeMs,
- int strengthBin) {
- mHistoryCur.states2 =
- (mHistoryCur.states2 & ~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
- | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
- }
-
- /**
- * Writes the current history item to history.
- */
- public void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs) {
- if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
- final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
- final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
- if (diffUptimeMs < (diffElapsedMs - 20)) {
- final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
- mHistoryAddTmp.setTo(mHistoryLastWritten);
- mHistoryAddTmp.wakelockTag = null;
- mHistoryAddTmp.wakeReasonTag = null;
- mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
- mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
- writeHistoryItem(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
- }
- }
- mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
- mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
- mTrackRunningHistoryUptimeMs = uptimeMs;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur);
- }
-
- private void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
- if (!mHaveBatteryLevel || !mRecordingHistory) {
- return;
- }
-
- final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
- final int diffStates = mHistoryLastWritten.states ^ (cur.states & mActiveHistoryStates);
- final int diffStates2 = mHistoryLastWritten.states2 ^ (cur.states2 & mActiveHistoryStates2);
- final int lastDiffStates = mHistoryLastWritten.states ^ mHistoryLastLastWritten.states;
- final int lastDiffStates2 = mHistoryLastWritten.states2 ^ mHistoryLastLastWritten.states2;
- if (DEBUG) {
- Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
- + Integer.toHexString(diffStates) + " lastDiff="
- + Integer.toHexString(lastDiffStates) + " diff2="
- + Integer.toHexString(diffStates2) + " lastDiff2="
- + Integer.toHexString(lastDiffStates2));
- }
- if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
- && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
- && (diffStates2 & lastDiffStates2) == 0
- && (!mHistoryLastWritten.tagsFirstOccurrence && !cur.tagsFirstOccurrence)
- && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
- && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
- && mHistoryLastWritten.stepDetails == null
- && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
- || cur.eventCode == HistoryItem.EVENT_NONE)
- && mHistoryLastWritten.batteryLevel == cur.batteryLevel
- && mHistoryLastWritten.batteryStatus == cur.batteryStatus
- && mHistoryLastWritten.batteryHealth == cur.batteryHealth
- && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
- && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
- && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
- // We can merge this new change in with the last one. Merging is
- // allowed as long as only the states have changed, and within those states
- // as long as no bit has changed both between now and the last entry, as
- // well as the last entry and the one before it (so we capture any toggles).
- if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
- mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
- mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
- mHistoryBufferLastPos = -1;
- elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
- // If the last written history had a wakelock tag, we need to retain it.
- // Note that the condition above made sure that we aren't in a case where
- // both it and the current history item have a wakelock tag.
- if (mHistoryLastWritten.wakelockTag != null) {
- cur.wakelockTag = cur.localWakelockTag;
- cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
- }
- // If the last written history had a wake reason tag, we need to retain it.
- // Note that the condition above made sure that we aren't in a case where
- // both it and the current history item have a wakelock tag.
- if (mHistoryLastWritten.wakeReasonTag != null) {
- cur.wakeReasonTag = cur.localWakeReasonTag;
- cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
- }
- // If the last written history had an event, we need to retain it.
- // Note that the condition above made sure that we aren't in a case where
- // both it and the current history item have an event.
- if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
- cur.eventCode = mHistoryLastWritten.eventCode;
- cur.eventTag = cur.localEventTag;
- cur.eventTag.setTo(mHistoryLastWritten.eventTag);
- }
- mHistoryLastWritten.setTo(mHistoryLastLastWritten);
- }
- final int dataSize = mHistoryBuffer.dataSize();
-
- if (dataSize >= mMaxHistoryBufferSize) {
- if (mMaxHistoryBufferSize == 0) {
- Slog.wtf(TAG, "mMaxHistoryBufferSize should not be zero when writing history");
- mMaxHistoryBufferSize = 1024;
- }
-
- //open a new history file.
- final long start = SystemClock.uptimeMillis();
- writeHistory();
- if (DEBUG) {
- Slog.d(TAG, "addHistoryBufferLocked writeHistory took ms:"
- + (SystemClock.uptimeMillis() - start));
- }
- startNextFile();
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
- mHistoryBuffer.setDataCapacity(mMaxHistoryBufferSize / 2);
- mHistoryBufferLastPos = -1;
- mHistoryLastWritten.clear();
- mHistoryLastLastWritten.clear();
-
- // Mark every entry in the pool with a flag indicating that the tag
- // has not yet been encountered while writing the current history buffer.
- for (Map.Entry<HistoryTag, Integer> entry : mHistoryTagPool.entrySet()) {
- entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
- }
- // Make a copy of mHistoryCur.
- HistoryItem copy = new HistoryItem();
- copy.setTo(cur);
- // startRecordingHistory will reset mHistoryCur.
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
- // Add the copy into history buffer.
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, copy, HistoryItem.CMD_UPDATE);
- return;
- }
-
- if (dataSize == 0) {
- // The history is currently empty; we need it to start with a time stamp.
- cur.currentTime = mClock.currentTimeMillis();
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_RESET);
- }
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_UPDATE);
- }
-
- private void writeHistoryItem(long elapsedRealtimeMs,
- @SuppressWarnings("UnusedVariable") long uptimeMs, HistoryItem cur, byte cmd) {
- if (mBatteryStatsHistoryIterator != null) {
- throw new IllegalStateException("Can't do this while iterating history!");
- }
- mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
- mHistoryLastLastWritten.setTo(mHistoryLastWritten);
- final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
- mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
- mHistoryLastWritten.tagsFirstOccurrence = hasTags;
- mHistoryLastWritten.states &= mActiveHistoryStates;
- mHistoryLastWritten.states2 &= mActiveHistoryStates2;
- writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
- mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
- cur.wakelockTag = null;
- cur.wakeReasonTag = null;
- cur.eventCode = HistoryItem.EVENT_NONE;
- cur.eventTag = null;
- cur.tagsFirstOccurrence = false;
- if (DEBUG) {
- Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
- + " now " + mHistoryBuffer.dataPosition()
- + " size is now " + mHistoryBuffer.dataSize());
- }
- }
-
- /*
- The history delta format uses flags to denote further data in subsequent ints in the parcel.
-
- There is always the first token, which may contain the delta time, or an indicator of
- the length of the time (int or long) following this token.
-
- First token: always present,
- 31 23 15 7 0
- █M|L|K|J|I|H|G|F█E|D|C|B|A|T|T|T█T|T|T|T|T|T|T|T█T|T|T|T|T|T|T|T█
-
- T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
- follows containing the time, and 0x7ffff indicates a long immediately follows with the
- delta time.
- A: battery level changed and an int follows with battery data.
- B: state changed and an int follows with state change data.
- C: state2 has changed and an int follows with state2 change data.
- D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
- E: event data has changed and an event struct follows.
- F: battery charge in coulombs has changed and an int with the charge follows.
- G: state flag denoting that the mobile radio was active.
- H: state flag denoting that the wifi radio was active.
- I: state flag denoting that a wifi scan occurred.
- J: state flag denoting that a wifi full lock was held.
- K: state flag denoting that the gps was on.
- L: state flag denoting that a wakelock was held.
- M: state flag denoting that the cpu was running.
-
- Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
- with the time delta.
-
- Battery level int: if A in the first token is set,
- 31 23 15 7 0
- █L|L|L|L|L|L|L|T█T|T|T|T|T|T|T|T█T|V|V|V|V|V|V|V█V|V|V|V|V|V|V|D█
-
- D: indicates that extra history details follow.
- V: the battery voltage.
- T: the battery temperature.
- L: the battery level (out of 100).
-
- State change int: if B in the first token is set,
- 31 23 15 7 0
- █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
-
- A: wifi multicast was on.
- B: battery was plugged in.
- C: screen was on.
- D: phone was scanning for signal.
- E: audio was on.
- F: a sensor was active.
-
- State2 change int: if C in the first token is set,
- 31 23 15 7 0
- █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
-
- A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
- B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
- C: a bluetooth scan was active.
- D: the camera was active.
- E: bluetooth was on.
- F: a phone call was active.
- G: the device was charging.
- H: 2 bits indicating the device-idle (doze) state: off, light, full
- I: the flashlight was on.
- J: wifi was on.
- K: wifi was running.
- L: video was playing.
- M: power save mode was on.
-
- Wakelock/wakereason struct: if D in the first token is set,
- Event struct: if E in the first token is set,
- History step details struct: if D in the battery level int is set,
-
- Battery charge int: if F in the first token is set, an int representing the battery charge
- in coulombs follows.
- */
- /**
- * Writes the delta between the previous and current history items into history buffer.
- */
- public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
- if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
- dest.writeInt(BatteryStatsHistory.DELTA_TIME_ABS);
- cur.writeToParcel(dest, 0);
- return;
- }
-
- final long deltaTime = cur.time - last.time;
- final int lastBatteryLevelInt = buildBatteryLevelInt(last);
- final int lastStateInt = buildStateInt(last);
-
- int deltaTimeToken;
- if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
- deltaTimeToken = BatteryStatsHistory.DELTA_TIME_LONG;
- } else if (deltaTime >= BatteryStatsHistory.DELTA_TIME_ABS) {
- deltaTimeToken = BatteryStatsHistory.DELTA_TIME_INT;
- } else {
- deltaTimeToken = (int) deltaTime;
- }
- int firstToken = deltaTimeToken | (cur.states & BatteryStatsHistory.DELTA_STATE_MASK);
- final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
- ? BatteryStatsHistory.BATTERY_DELTA_LEVEL_FLAG : 0;
- mLastHistoryStepLevel = cur.batteryLevel;
- final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
- final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
- if (batteryLevelIntChanged) {
- firstToken |= BatteryStatsHistory.DELTA_BATTERY_LEVEL_FLAG;
- }
- final int stateInt = buildStateInt(cur);
- final boolean stateIntChanged = stateInt != lastStateInt;
- if (stateIntChanged) {
- firstToken |= BatteryStatsHistory.DELTA_STATE_FLAG;
- }
- final boolean state2IntChanged = cur.states2 != last.states2;
- if (state2IntChanged) {
- firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG;
- }
- if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
- firstToken |= BatteryStatsHistory.DELTA_WAKELOCK_FLAG;
- }
- if (cur.eventCode != HistoryItem.EVENT_NONE) {
- firstToken |= BatteryStatsHistory.DELTA_EVENT_FLAG;
- }
-
- final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
- if (batteryChargeChanged) {
- firstToken |= BatteryStatsHistory.DELTA_BATTERY_CHARGE_FLAG;
- }
- dest.writeInt(firstToken);
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
- + " deltaTime=" + deltaTime);
- }
-
- if (deltaTimeToken >= BatteryStatsHistory.DELTA_TIME_INT) {
- if (deltaTimeToken == BatteryStatsHistory.DELTA_TIME_INT) {
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int) deltaTime);
- dest.writeInt((int) deltaTime);
- } else {
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
- dest.writeLong(deltaTime);
- }
- }
- if (batteryLevelIntChanged) {
- dest.writeInt(batteryLevelInt);
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
- + Integer.toHexString(batteryLevelInt)
- + " batteryLevel=" + cur.batteryLevel
- + " batteryTemp=" + cur.batteryTemperature
- + " batteryVolt=" + (int) cur.batteryVoltage);
- }
- }
- if (stateIntChanged) {
- dest.writeInt(stateInt);
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: stateToken=0x"
- + Integer.toHexString(stateInt)
- + " batteryStatus=" + cur.batteryStatus
- + " batteryHealth=" + cur.batteryHealth
- + " batteryPlugType=" + cur.batteryPlugType
- + " states=0x" + Integer.toHexString(cur.states));
- }
- }
- if (state2IntChanged) {
- dest.writeInt(cur.states2);
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: states2=0x"
- + Integer.toHexString(cur.states2));
- }
- }
- if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
- int wakeLockIndex;
- int wakeReasonIndex;
- if (cur.wakelockTag != null) {
- wakeLockIndex = writeHistoryTag(cur.wakelockTag);
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
- + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
- }
- } else {
- wakeLockIndex = 0xffff;
- }
- if (cur.wakeReasonTag != null) {
- wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
- + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
- }
- } else {
- wakeReasonIndex = 0xffff;
- }
- dest.writeInt((wakeReasonIndex << 16) | wakeLockIndex);
- if (cur.wakelockTag != null
- && (wakeLockIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- cur.wakelockTag.writeToParcel(dest, 0);
- cur.tagsFirstOccurrence = true;
- }
- if (cur.wakeReasonTag != null
- && (wakeReasonIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- cur.wakeReasonTag.writeToParcel(dest, 0);
- cur.tagsFirstOccurrence = true;
- }
- }
- if (cur.eventCode != HistoryItem.EVENT_NONE) {
- final int index = writeHistoryTag(cur.eventTag);
- final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
- dest.writeInt(codeAndIndex);
- if ((index & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- cur.eventTag.writeToParcel(dest, 0);
- cur.tagsFirstOccurrence = true;
- }
- if (DEBUG) {
- Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
- + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
- + cur.eventTag.string);
- }
- }
-
- cur.stepDetails = mStepDetailsCalculator.getHistoryStepDetails();
- if (includeStepDetails != 0) {
- cur.stepDetails.writeToParcel(dest);
- }
-
- if (batteryChargeChanged) {
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
- dest.writeInt(cur.batteryChargeUah);
- }
- dest.writeDouble(cur.modemRailChargeMah);
- dest.writeDouble(cur.wifiRailChargeMah);
- }
-
- private int buildBatteryLevelInt(HistoryItem h) {
- return ((((int) h.batteryLevel) << 25) & 0xfe000000)
- | ((((int) h.batteryTemperature) << 15) & 0x01ff8000)
- | ((((int) h.batteryVoltage) << 1) & 0x00007ffe);
- }
-
- private int buildStateInt(HistoryItem h) {
- int plugType = 0;
- if ((h.batteryPlugType & BatteryManager.BATTERY_PLUGGED_AC) != 0) {
- plugType = 1;
- } else if ((h.batteryPlugType & BatteryManager.BATTERY_PLUGGED_USB) != 0) {
- plugType = 2;
- } else if ((h.batteryPlugType & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
- plugType = 3;
- }
- return ((h.batteryStatus & BatteryStatsHistory.STATE_BATTERY_STATUS_MASK)
- << BatteryStatsHistory.STATE_BATTERY_STATUS_SHIFT)
- | ((h.batteryHealth & BatteryStatsHistory.STATE_BATTERY_HEALTH_MASK)
- << BatteryStatsHistory.STATE_BATTERY_HEALTH_SHIFT)
- | ((plugType & BatteryStatsHistory.STATE_BATTERY_PLUG_MASK)
- << BatteryStatsHistory.STATE_BATTERY_PLUG_SHIFT)
- | (h.states & (~BatteryStatsHistory.STATE_BATTERY_MASK));
- }
-
- /**
- * Returns the index for the specified tag. If this is the first time the tag is encountered
- * while writing the current history buffer, the method returns
- * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
- */
- private int writeHistoryTag(HistoryTag tag) {
- if (tag.string == null) {
- Slog.wtfStack(TAG, "writeHistoryTag called with null name");
- }
-
- final int stringLength = tag.string.length();
- if (stringLength > MAX_HISTORY_TAG_STRING_LENGTH) {
- Slog.e(TAG, "Long battery history tag: " + tag.string);
- tag.string = tag.string.substring(0, MAX_HISTORY_TAG_STRING_LENGTH);
- }
-
- Integer idxObj = mHistoryTagPool.get(tag);
- int idx;
- if (idxObj != null) {
- idx = idxObj;
- if ((idx & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- mHistoryTagPool.put(tag, idx & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
- }
- return idx;
- } else if (mNextHistoryTagIdx < HISTORY_TAG_INDEX_LIMIT) {
- idx = mNextHistoryTagIdx;
- HistoryTag key = new HistoryTag();
- key.setTo(tag);
- tag.poolIdx = idx;
- mHistoryTagPool.put(key, idx);
- mNextHistoryTagIdx++;
-
- mNumHistoryTagChars += stringLength + 1;
- if (mHistoryTags != null) {
- mHistoryTags.put(idx, key);
- }
- return idx | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
- } else {
- // Tag pool overflow: include the tag itself in the parcel
- return HISTORY_TAG_INDEX_LIMIT | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
- }
- }
-
- /**
- * Don't allow any more batching in to the current history event.
- */
- public void commitCurrentHistoryBatchLocked() {
- mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
- }
-
- /**
- * Saves the accumulated history buffer in the active file, see {@link #getActiveFile()} .
- */
- public void writeHistory() {
- if (mActiveFile == null) {
- Slog.w(TAG, "writeHistory: no history file associated with this instance");
- return;
- }
-
- Parcel p = Parcel.obtain();
- try {
- final long start = SystemClock.uptimeMillis();
- writeHistoryBuffer(p);
- if (DEBUG) {
- Slog.d(TAG, "writeHistoryBuffer duration ms:"
- + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
- }
- writeParcelToFileLocked(p, mActiveFile);
- } finally {
- p.recycle();
- }
- }
-
- /**
- * Reads history buffer from a persisted Parcel.
- */
- public void readHistoryBuffer(Parcel in) throws ParcelFormatException {
- final int version = in.readInt();
- if (version != BatteryStatsHistory.VERSION) {
- Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
- + ", expected " + BatteryStatsHistory.VERSION + "; erasing old stats");
- return;
- }
-
- final long historyBaseTime = in.readLong();
-
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
-
- int bufSize = in.readInt();
- int curPos = in.dataPosition();
- if (bufSize >= (mMaxHistoryBufferSize * 100)) {
- throw new ParcelFormatException(
- "File corrupt: history data buffer too large " + bufSize);
- } else if ((bufSize & ~3) != bufSize) {
- throw new ParcelFormatException(
- "File corrupt: history data buffer not aligned " + bufSize);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
- + " bytes at " + curPos);
- }
- mHistoryBuffer.appendFrom(in, curPos, bufSize);
- in.setDataPosition(curPos + bufSize);
- }
-
- if (DEBUG) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** OLD mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
- mHistoryBaseTimeMs = historyBaseTime;
- if (DEBUG) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** NEW mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
-
- // We are just arbitrarily going to insert 1 minute from the sample of
- // the last run until samples in this run.
- if (mHistoryBaseTimeMs > 0) {
- long oldnow = mClock.elapsedRealtime();
- mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
- if (DEBUG) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
- }
- }
-
- private void writeHistoryBuffer(Parcel out) {
- if (DEBUG) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** WRITING mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- sb.append(" mLastHistoryElapsedRealtimeMs: ");
- TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
- out.writeInt(BatteryStatsHistory.VERSION);
- out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
- out.writeInt(mHistoryBuffer.dataSize());
- if (DEBUG) {
- Slog.i(TAG, "***************** WRITING HISTORY: "
- + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
- }
- out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
- }
-
- private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
- FileOutputStream fos = null;
- mWriteLock.lock();
- try {
- final long startTimeMs = SystemClock.uptimeMillis();
- fos = file.startWrite();
- fos.write(p.marshall());
- fos.flush();
- file.finishWrite(fos);
- if (DEBUG) {
- Slog.d(TAG, "writeParcelToFileLocked file:" + file.getBaseFile().getPath()
- + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
- + " bytes:" + p.dataSize());
- }
- com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "batterystats", SystemClock.uptimeMillis() - startTimeMs);
- } catch (IOException e) {
- Slog.w(TAG, "Error writing battery statistics", e);
- file.failWrite(fos);
- } finally {
- mWriteLock.unlock();
- }
- }
-
- /**
- * Returns the total number of history tags in the tag pool.
- */
- public int getHistoryStringPoolSize() {
- return mHistoryTagPool.size();
- }
-
- /**
- * Returns the total number of bytes occupied by the history tag pool.
- */
- public int getHistoryStringPoolBytes() {
- return mNumHistoryTagChars;
- }
-
- /**
- * Returns the string held by the requested history tag.
- */
- public String getHistoryTagPoolString(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.string : null;
- }
-
- /**
- * Returns the UID held by the requested history tag.
- */
- public int getHistoryTagPoolUid(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.uid : Process.INVALID_UID;
- }
-
- private void ensureHistoryTagArray() {
- if (mHistoryTags != null) {
- return;
- }
-
- mHistoryTags = new SparseArray<>(mHistoryTagPool.size());
- for (Map.Entry<HistoryTag, Integer> entry : mHistoryTagPool.entrySet()) {
- mHistoryTags.put(entry.getValue() & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG,
- entry.getKey());
- }
- }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index 1bf878cb9119..de8b414c4b78 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -36,6 +36,7 @@ public class BatteryStatsHistoryIterator {
public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) {
mBatteryStatsHistory = history;
+ mBatteryStatsHistory.startIteratingHistory();
}
/**
@@ -230,11 +231,4 @@ public class BatteryStatsHistoryIterator {
out.batteryTemperature = (short) ((batteryLevelInt & 0x01ff8000) >>> 15);
out.batteryVoltage = (char) ((batteryLevelInt & 0x00007ffe) >>> 1);
}
-
- /**
- * Should be called when iteration is complete.
- */
- public void close() {
- mBatteryStatsHistory.finishIteratingHistory();
- }
}
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index d8522658d747..17cfbfc63f65 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -720,19 +720,22 @@ static jint util_texImage2D(JNIEnv *env, jclass clazz, jint target, jint level,
jint internalformat, jobject bitmapObj, jint type, jint border)
{
graphics::Bitmap bitmap(env, bitmapObj);
- AndroidBitmapInfo bitmapInfo = bitmap.getInfo();
+ if (bitmap.isValid() && bitmap.getPixels() != nullptr) {
+ AndroidBitmapInfo bitmapInfo = bitmap.getInfo();
- if (internalformat < 0) {
- internalformat = getInternalFormat(bitmapInfo.format);
- }
- if (type < 0) {
- type = getType(bitmapInfo.format);
- }
+ if (internalformat < 0) {
+ internalformat = getInternalFormat(bitmapInfo.format);
+ }
+ if (type < 0) {
+ type = getType(bitmapInfo.format);
+ }
- if (checkInternalFormat(bitmapInfo.format, internalformat, type)) {
- glTexImage2D(target, level, internalformat, bitmapInfo.width, bitmapInfo.height, border,
- getPixelFormatFromInternalFormat(internalformat), type, bitmap.getPixels());
- return 0;
+ if (checkInternalFormat(bitmapInfo.format, internalformat, type)) {
+ glTexImage2D(target, level, internalformat, bitmapInfo.width, bitmapInfo.height, border,
+ getPixelFormatFromInternalFormat(internalformat), type,
+ bitmap.getPixels());
+ return 0;
+ }
}
return -1;
}
@@ -741,19 +744,21 @@ static jint util_texSubImage2D(JNIEnv *env, jclass clazz, jint target, jint leve
jint xoffset, jint yoffset, jobject bitmapObj, jint format, jint type)
{
graphics::Bitmap bitmap(env, bitmapObj);
- AndroidBitmapInfo bitmapInfo = bitmap.getInfo();
-
- int internalFormat = getInternalFormat(bitmapInfo.format);
- if (format < 0) {
- format = getPixelFormatFromInternalFormat(internalFormat);
- if (format == GL_PALETTE8_RGBA8_OES)
- return -1; // glCompressedTexSubImage2D() not supported
- }
+ if (bitmap.isValid() && bitmap.getPixels() != nullptr) {
+ AndroidBitmapInfo bitmapInfo = bitmap.getInfo();
+
+ int internalFormat = getInternalFormat(bitmapInfo.format);
+ if (format < 0) {
+ format = getPixelFormatFromInternalFormat(internalFormat);
+ if (format == GL_PALETTE8_RGBA8_OES)
+ return -1; // glCompressedTexSubImage2D() not supported
+ }
- if (checkInternalFormat(bitmapInfo.format, internalFormat, type)) {
- glTexSubImage2D(target, level, xoffset, yoffset, bitmapInfo.width, bitmapInfo.height,
- format, type, bitmap.getPixels());
- return 0;
+ if (checkInternalFormat(bitmapInfo.format, internalFormat, type)) {
+ glTexSubImage2D(target, level, xoffset, yoffset, bitmapInfo.width, bitmapInfo.height,
+ format, type, bitmap.getPixels());
+ return 0;
+ }
}
return -1;
}
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
index 8533a5994d33..b0dab90b6add 100644
--- a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
@@ -16,92 +16,98 @@
-->
<!-- Layout for TvPipMenuView -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/tv_pip_menu"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center|top">
+ android:id="@+id/tv_pip_menu"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center|top">
<!-- Matches the PiP app content -->
- <View
+ <FrameLayout
android:id="@+id/tv_pip"
android:layout_width="0dp"
android:layout_height="0dp"
- android:alpha="0"
- android:background="@color/tv_pip_menu_background"
android:layout_marginTop="@dimen/pip_menu_outer_space"
android:layout_marginStart="@dimen/pip_menu_outer_space"
- android:layout_marginEnd="@dimen/pip_menu_outer_space"/>
-
- <ScrollView
- android:id="@+id/tv_pip_menu_scroll"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignTop="@+id/tv_pip"
- android:layout_alignStart="@+id/tv_pip"
- android:layout_alignEnd="@+id/tv_pip"
- android:layout_alignBottom="@+id/tv_pip"
- android:scrollbars="none"
- android:visibility="gone"/>
-
- <HorizontalScrollView
- android:id="@+id/tv_pip_menu_horizontal_scroll"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignTop="@+id/tv_pip"
- android:layout_alignStart="@+id/tv_pip"
- android:layout_alignEnd="@+id/tv_pip"
- android:layout_alignBottom="@+id/tv_pip"
- android:scrollbars="none">
-
- <LinearLayout
- android:id="@+id/tv_pip_menu_action_buttons"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:alpha="0">
+ android:layout_marginEnd="@dimen/pip_menu_outer_space">
- <Space
- android:layout_width="@dimen/pip_menu_button_wrapper_margin"
- android:layout_height="@dimen/pip_menu_button_wrapper_margin"/>
-
- <com.android.wm.shell.common.TvWindowMenuActionButton
- android:id="@+id/tv_pip_menu_fullscreen_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/pip_ic_fullscreen_white"
- android:text="@string/pip_fullscreen" />
+ <View
+ android:id="@+id/tv_pip_menu_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/tv_pip_menu_background"
+ android:alpha="0"/>
- <com.android.wm.shell.common.TvWindowMenuActionButton
- android:id="@+id/tv_pip_menu_close_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/pip_ic_close_white"
- android:text="@string/pip_close" />
+ <View
+ android:id="@+id/tv_pip_menu_dim_layer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/tv_pip_menu_dim_layer"
+ android:alpha="0"/>
- <!-- More TvPipMenuActionButtons may be added here at runtime. -->
+ <ScrollView
+ android:id="@+id/tv_pip_menu_scroll"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none"
+ android:visibility="gone"/>
- <com.android.wm.shell.common.TvWindowMenuActionButton
- android:id="@+id/tv_pip_menu_move_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/pip_ic_move_white"
- android:text="@string/pip_move" />
+ <HorizontalScrollView
+ android:id="@+id/tv_pip_menu_horizontal_scroll"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none">
- <com.android.wm.shell.common.TvWindowMenuActionButton
- android:id="@+id/tv_pip_menu_expand_button"
+ <LinearLayout
+ android:id="@+id/tv_pip_menu_action_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:src="@drawable/pip_ic_collapse"
- android:visibility="gone"
- android:text="@string/pip_collapse" />
-
- <Space
- android:layout_width="@dimen/pip_menu_button_wrapper_margin"
- android:layout_height="@dimen/pip_menu_button_wrapper_margin"/>
-
- </LinearLayout>
- </HorizontalScrollView>
+ android:orientation="horizontal"
+ android:alpha="0">
+
+ <Space
+ android:layout_width="@dimen/pip_menu_button_wrapper_margin"
+ android:layout_height="@dimen/pip_menu_button_wrapper_margin"/>
+
+ <com.android.wm.shell.pip.tv.TvPipMenuActionButton
+ android:id="@+id/tv_pip_menu_fullscreen_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/pip_ic_fullscreen_white"
+ android:text="@string/pip_fullscreen" />
+
+ <com.android.wm.shell.pip.tv.TvPipMenuActionButton
+ android:id="@+id/tv_pip_menu_close_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/pip_ic_close_white"
+ android:text="@string/pip_close" />
+
+ <!-- More TvPipMenuActionButtons may be added here at runtime. -->
+
+ <com.android.wm.shell.pip.tv.TvPipMenuActionButton
+ android:id="@+id/tv_pip_menu_move_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/pip_ic_move_white"
+ android:text="@string/pip_move" />
+
+ <com.android.wm.shell.pip.tv.TvPipMenuActionButton
+ android:id="@+id/tv_pip_menu_expand_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/pip_ic_collapse"
+ android:visibility="gone"
+ android:text="@string/pip_collapse" />
+
+ <Space
+ android:layout_width="@dimen/pip_menu_button_wrapper_margin"
+ android:layout_height="@dimen/pip_menu_button_wrapper_margin"/>
+
+ </LinearLayout>
+ </HorizontalScrollView>
+ </FrameLayout>
+ <!-- Frame around the content, just overlapping the corners to make them round -->
<View
android:id="@+id/tv_pip_border"
android:layout_width="0dp"
@@ -111,6 +117,7 @@
android:layout_marginEnd="@dimen/pip_menu_outer_space_frame"
android:background="@drawable/tv_pip_menu_border"/>
+ <!-- Temporarily extending the background to show an edu text hint for opening the menu -->
<FrameLayout
android:id="@+id/tv_pip_menu_edu_text_container"
android:layout_width="match_parent"
@@ -138,6 +145,7 @@
android:textAppearance="@style/TvPipEduText"/>
</FrameLayout>
+ <!-- Frame around the PiP content + edu text hint - used to highlight open menu -->
<View
android:id="@+id/tv_pip_menu_frame"
android:layout_width="match_parent"
@@ -145,7 +153,8 @@
android:layout_margin="@dimen/pip_menu_outer_space_frame"
android:background="@drawable/tv_pip_menu_border"/>
- <com.android.wm.shell.common.TvWindowMenuActionButton
+ <!-- Move menu -->
+ <com.android.wm.shell.pip.tv.TvPipMenuActionButton
android:id="@+id/tv_pip_menu_done_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/libs/WindowManager/Shell/res/values/colors_tv.xml b/libs/WindowManager/Shell/res/values/colors_tv.xml
index 3e71c1010278..e6933ca3fce6 100644
--- a/libs/WindowManager/Shell/res/values/colors_tv.xml
+++ b/libs/WindowManager/Shell/res/values/colors_tv.xml
@@ -25,6 +25,7 @@
<color name="tv_window_menu_icon_bg_unfocused">#990E0E0F</color>
<color name="tv_pip_menu_focus_border">#E8EAED</color>
+ <color name="tv_pip_menu_dim_layer">#990E0E0F</color>
<color name="tv_pip_menu_background">#1E232C</color>
<color name="tv_pip_edu_text">#99D2E3FC</color>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
index 4d7c8465bcc2..97e017a65b04 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
@@ -97,6 +97,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
private final ImageView mArrowLeft;
private final TvWindowMenuActionButton mA11yDoneButton;
+ private final View mPipBackground;
+ private final View mDimLayer;
+
private final ScrollView mScrollView;
private final HorizontalScrollView mHorizontalScrollView;
private View mFocusedButton;
@@ -148,6 +151,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
mExpandButton = findViewById(R.id.tv_pip_menu_expand_button);
mExpandButton.setOnClickListener(this);
+ mPipBackground = findViewById(R.id.tv_pip_menu_background);
+ mDimLayer = findViewById(R.id.tv_pip_menu_dim_layer);
+
mScrollView = findViewById(R.id.tv_pip_menu_scroll);
mHorizontalScrollView = findViewById(R.id.tv_pip_menu_horizontal_scroll);
@@ -231,7 +237,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
mCurrentPipBounds.width() / (float) mCurrentPipBounds.height(),
finishBounds.width() / (float) finishBounds.height());
if (ratioChanged) {
- mPipView.animate()
+ mPipBackground.animate()
.alpha(1f)
.setInterpolator(TvPipInterpolators.EXIT)
.setDuration(mResizeAnimationDuration / 2)
@@ -272,7 +278,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
"%s: onPipTransitionFinished()", TAG);
// Fade in content by fading out view on top.
- mPipView.animate()
+ mPipBackground.animate()
.alpha(0f)
.setDuration(mResizeAnimationDuration / 2)
.setInterpolator(TvPipInterpolators.ENTER)
@@ -770,6 +776,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
refocusPreviousButton();
}
animateAlphaTo(show ? 1 : 0, mActionButtonsContainer);
+ animateAlphaTo(show ? 1 : 0, mDimLayer);
}
private void setFrameHighlighted(boolean highlighted) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index 0a54b8c016fb..a8154e818a04 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -32,7 +32,6 @@ import com.android.server.wm.flicker.statusBarLayerPositionAtStartAndEnd
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.taskBarLayerIsVisibleAtStartAndEnd
import com.android.server.wm.flicker.taskBarWindowIsAlwaysVisible
-import com.android.server.wm.traces.common.ComponentMatcher
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume
import org.junit.Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 8b717a0cb75e..06361f9ca4ab 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -17,10 +17,10 @@
@file:JvmName("CommonConstants")
package com.android.wm.shell.flicker
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
-val APP_PAIR_SPLIT_DIVIDER_COMPONENT = ComponentMatcher("", "AppPairSplitDivider#")
-val DOCKED_STACK_DIVIDER_COMPONENT = ComponentMatcher("", "DockedStackDivider#")
-val SPLIT_SCREEN_DIVIDER_COMPONENT = ComponentMatcher("", "StageCoordinatorSplitDivider#")
-val SPLIT_DECOR_MANAGER = ComponentMatcher("", "SplitDecorManager#")
+val APP_PAIR_SPLIT_DIVIDER_COMPONENT = ComponentNameMatcher("", "AppPairSplitDivider#")
+val DOCKED_STACK_DIVIDER_COMPONENT = ComponentNameMatcher("", "DockedStackDivider#")
+val SPLIT_SCREEN_DIVIDER_COMPONENT = ComponentNameMatcher("", "StageCoordinatorSplitDivider#")
+val SPLIT_DECOR_MANAGER = ComponentNameMatcher("", "SplitDecorManager#")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt
index ffbac39c6078..826cc2ef16d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
class AppPairsHelper(
instrumentation: Instrumentation,
activityLabel: String,
- component: IComponentMatcher
+ component: ComponentNameMatcher
) : BaseAppHelper(instrumentation, activityLabel, component)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
index c4379e9a27cc..01ba9907c24c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
@@ -26,13 +26,13 @@ import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.compatibility.common.util.SystemUtil
import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.IComponentNameMatcher
import java.io.IOException
abstract class BaseAppHelper(
instrumentation: Instrumentation,
launcherName: String,
- component: IComponentMatcher
+ component: IComponentNameMatcher
) : StandardAppHelper(
instrumentation,
launcherName,
@@ -46,9 +46,6 @@ abstract class BaseAppHelper(
hasSystemFeature(FEATURE_LEANBACK) || hasSystemFeature(FEATURE_LEANBACK_ONLY)
}
- val defaultWindowName: String
- get() = toWindowName()
-
val ui: UiObject2?
get() = uiDevice.findObject(appSelector)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/MultiWindowHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/MultiWindowHelper.kt
index 92b1d216f5ab..245a82f938b3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/MultiWindowHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/MultiWindowHelper.kt
@@ -19,12 +19,12 @@ package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
import android.content.Context
import android.provider.Settings
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
class MultiWindowHelper(
instrumentation: Instrumentation,
activityLabel: String,
- componentsInfo: IComponentMatcher
+ componentsInfo: ComponentNameMatcher
) : BaseAppHelper(instrumentation, activityLabel, componentsInfo) {
companion object {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index a1226e682e05..240e8711d43e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -28,6 +28,7 @@ import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.IComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.SPLIT_DECOR_MANAGER
@@ -37,8 +38,8 @@ import com.android.wm.shell.flicker.testapp.Components
class SplitScreenHelper(
instrumentation: Instrumentation,
activityLabel: String,
- componentsInfo: IComponentMatcher
-) : BaseAppHelper(instrumentation, activityLabel, componentsInfo) {
+ componentInfo: IComponentNameMatcher
+) : BaseAppHelper(instrumentation, activityLabel, componentInfo) {
companion object {
const val TEST_REPETITIONS = 1
@@ -280,12 +281,12 @@ class SplitScreenHelper(
fun copyContentFromLeftToRight(
instrumentation: Instrumentation,
device: UiDevice,
- sourceApp: IComponentMatcher,
- destinationApp: IComponentMatcher,
+ sourceApp: IComponentNameMatcher,
+ destinationApp: IComponentNameMatcher,
) {
// Copy text from sourceApp
val textView = device.wait(Until.findObject(
- By.res(sourceApp.packageNames.firstOrNull(), "SplitScreenTest")), TIMEOUT_MS)
+ By.res(sourceApp.packageName, "SplitScreenTest")), TIMEOUT_MS)
longPress(instrumentation, textView.getVisibleCenter())
val copyBtn = device.wait(Until.findObject(By.text("Copy")), TIMEOUT_MS)
@@ -293,7 +294,7 @@ class SplitScreenHelper(
// Paste text to destinationApp
val editText = device.wait(Until.findObject(
- By.res(destinationApp.packageNames.firstOrNull(), "plain_text_input")), TIMEOUT_MS)
+ By.res(destinationApp.packageName, "plain_text_input")), TIMEOUT_MS)
longPress(instrumentation, editText.getVisibleCenter())
val pasteBtn = device.wait(Until.findObject(By.text("Paste")), TIMEOUT_MS)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 045022414fe0..d194472b9000 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -25,7 +25,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -155,9 +155,9 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
@Test
fun launcherLayerBecomesVisible() {
testSpec.assertLayers {
- isInvisible(ComponentMatcher.LAUNCHER)
+ isInvisible(ComponentNameMatcher.LAUNCHER)
.then()
- .isVisible(ComponentMatcher.LAUNCHER)
+ .isVisible(ComponentNameMatcher.LAUNCHER)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index dff447b97b9b..507562b00f4f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -30,7 +30,6 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
index 33f787182868..fd1fe65fa3a8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
@@ -23,7 +23,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentMatcher.Companion.LAUNCHER
+import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.LAUNCHER
import org.junit.Test
/**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
index 5b5b9fc174f6..31a39c190dd6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
@@ -24,7 +24,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -63,9 +63,9 @@ class ExitPipWithSwipeDownTest(testSpec: FlickerTestParameter) : ExitPipTransiti
val pipCenterY = pipRegion.centerY()
val displayCenterX = device.displayWidth / 2
val barComponent = if (testSpec.isTablet) {
- ComponentMatcher.TASK_BAR
+ ComponentNameMatcher.TASK_BAR
} else {
- ComponentMatcher.NAV_BAR
+ ComponentNameMatcher.NAV_BAR
}
val barLayerHeight = wmHelper.currentState.layerState
.getLayerWithBuffer(barComponent)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 1c0bd0caa901..fd661cfc3ee1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -25,7 +25,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -151,7 +151,7 @@ class ExpandPipOnDoubleClickTest(testSpec: FlickerTestParameter) : PipTransition
@Test
fun launcherIsAlwaysVisible() {
testSpec.assertLayers {
- isVisible(ComponentMatcher.LAUNCHER)
+ isVisible(ComponentNameMatcher.LAUNCHER)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 911d402cfde7..454927e57aa2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -28,7 +28,7 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.wm.shell.flicker.helpers.ImeAppHelper
import org.junit.Assume.assumeFalse
import org.junit.Before
@@ -105,7 +105,7 @@ open class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testS
@Test
open fun pipIsAboveAppWindow() {
testSpec.assertWmTag(TAG_IME_VISIBLE) {
- isAboveWindow(ComponentMatcher.IME, pipApp)
+ isAboveWindow(ComponentNameMatcher.IME, pipApp)
}
}
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 9a4bda2ee1df..3c67edc9a428 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -125,9 +125,14 @@ Typeface* Typeface::createWithDifferentBaseWeight(Typeface* src, int weight) {
}
Typeface* Typeface::createFromFamilies(std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
- int weight, int italic) {
+ int weight, int italic, const Typeface* fallback) {
Typeface* result = new Typeface;
- result->fFontCollection = minikin::FontCollection::create(families);
+ if (fallback == nullptr) {
+ result->fFontCollection = minikin::FontCollection::create(std::move(families));
+ } else {
+ result->fFontCollection =
+ fallback->fFontCollection->createCollectionWithFamilies(std::move(families));
+ }
if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) {
int weightFromFont;
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 0c3ef01ab26b..565136e53676 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -78,7 +78,8 @@ public:
Typeface* src, const std::vector<minikin::FontVariation>& variations);
static Typeface* createFromFamilies(
- std::vector<std::shared_ptr<minikin::FontFamily>>&& families, int weight, int italic);
+ std::vector<std::shared_ptr<minikin::FontFamily>>&& families, int weight, int italic,
+ const Typeface* fallback);
static void setDefault(const Typeface* face);
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index f5ed5689e4e8..209b35c5537c 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -109,27 +109,14 @@ static jint Typeface_getWeight(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) {
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
jlong fallbackPtr, int weight, int italic) {
ScopedLongArrayRO families(env, familyArray);
- std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
Typeface* typeface = (fallbackPtr == 0) ? nullptr : toTypeface(fallbackPtr);
- if (typeface != nullptr) {
- const std::shared_ptr<minikin::FontCollection>& fallbackCollection =
- toTypeface(fallbackPtr)->fFontCollection;
- familyVec.reserve(families.size() + fallbackCollection->getFamilyCount());
- for (size_t i = 0; i < families.size(); i++) {
- FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
- familyVec.emplace_back(family->family);
- }
- for (size_t i = 0; i < fallbackCollection->getFamilyCount(); i++) {
- familyVec.emplace_back(fallbackCollection->getFamilyAt(i));
- }
- } else {
- familyVec.reserve(families.size());
- for (size_t i = 0; i < families.size(); i++) {
- FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
- familyVec.emplace_back(family->family);
- }
+ std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
+ familyVec.reserve(families.size());
+ for (size_t i = 0; i < families.size(); i++) {
+ FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
+ familyVec.emplace_back(family->family);
}
- return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic));
+ return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic, typeface));
}
// CriticalNative
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 81bcb4e609df..c5196eeccea3 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -54,8 +54,6 @@ typedef void(VKAPI_PTR* PFN_vkFrameBoundaryANDROID)(VkDevice device, VkSemaphore
#include <SkColorSpace.h>
#include <SkRefCnt.h>
-class GrVkExtensions;
-
namespace android {
namespace uirenderer {
namespace renderthread {
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index 25cc8ca0dafb..499afa039d1f 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -73,7 +73,8 @@ std::vector<std::shared_ptr<minikin::FontFamily>> makeSingleFamlyVector(const ch
TEST(TypefaceTest, resolveDefault_and_setDefaultTest) {
std::unique_ptr<Typeface> regular(Typeface::createFromFamilies(
- makeSingleFamlyVector(kRobotoVariable), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ makeSingleFamlyVector(kRobotoVariable), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE,
+ nullptr /* fallback */));
EXPECT_EQ(regular.get(), Typeface::resolveDefault(regular.get()));
// Keep the original to restore it later.
@@ -351,24 +352,24 @@ TEST(TypefaceTest, createAbsolute) {
TEST(TypefaceTest, createFromFamilies_Single) {
// In Java, new
// Typeface.Builder("Roboto-Regular.ttf").setWeight(400).setItalic(false).build();
- std::unique_ptr<Typeface> regular(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoVariable), 400, false));
+ std::unique_ptr<Typeface> regular(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoVariable), 400, false, nullptr /* fallback */));
EXPECT_EQ(400, regular->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, regular->fStyle.slant());
EXPECT_EQ(Typeface::kNormal, regular->fAPIStyle);
// In Java, new
// Typeface.Builder("Roboto-Regular.ttf").setWeight(700).setItalic(false).build();
- std::unique_ptr<Typeface> bold(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoVariable), 700, false));
+ std::unique_ptr<Typeface> bold(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoVariable), 700, false, nullptr /* fallback */));
EXPECT_EQ(700, bold->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java, new
// Typeface.Builder("Roboto-Regular.ttf").setWeight(400).setItalic(true).build();
- std::unique_ptr<Typeface> italic(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoVariable), 400, true));
+ std::unique_ptr<Typeface> italic(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoVariable), 400, true, nullptr /* fallback */));
EXPECT_EQ(400, italic->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
@@ -376,8 +377,8 @@ TEST(TypefaceTest, createFromFamilies_Single) {
// In Java,
// new
// Typeface.Builder("Roboto-Regular.ttf").setWeight(700).setItalic(true).build();
- std::unique_ptr<Typeface> boldItalic(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoVariable), 700, true));
+ std::unique_ptr<Typeface> boldItalic(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoVariable), 700, true, nullptr /* fallback */));
EXPECT_EQ(700, boldItalic->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
@@ -385,8 +386,8 @@ TEST(TypefaceTest, createFromFamilies_Single) {
// In Java,
// new
// Typeface.Builder("Roboto-Regular.ttf").setWeight(1100).setItalic(false).build();
- std::unique_ptr<Typeface> over1000(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoVariable), 1100, false));
+ std::unique_ptr<Typeface> over1000(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoVariable), 1100, false, nullptr /* fallback */));
EXPECT_EQ(1000, over1000->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, over1000->fStyle.slant());
EXPECT_EQ(Typeface::kBold, over1000->fAPIStyle);
@@ -394,30 +395,33 @@ TEST(TypefaceTest, createFromFamilies_Single) {
TEST(TypefaceTest, createFromFamilies_Single_resolveByTable) {
// In Java, new Typeface.Builder("Family-Regular.ttf").build();
- std::unique_ptr<Typeface> regular(Typeface::createFromFamilies(
- makeSingleFamlyVector(kRegularFont), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> regular(
+ Typeface::createFromFamilies(makeSingleFamlyVector(kRegularFont), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, nullptr /* fallback */));
EXPECT_EQ(400, regular->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, regular->fStyle.slant());
EXPECT_EQ(Typeface::kNormal, regular->fAPIStyle);
// In Java, new Typeface.Builder("Family-Bold.ttf").build();
- std::unique_ptr<Typeface> bold(Typeface::createFromFamilies(
- makeSingleFamlyVector(kBoldFont), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> bold(
+ Typeface::createFromFamilies(makeSingleFamlyVector(kBoldFont), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, nullptr /* fallback */));
EXPECT_EQ(700, bold->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java, new Typeface.Builder("Family-Italic.ttf").build();
- std::unique_ptr<Typeface> italic(Typeface::createFromFamilies(
- makeSingleFamlyVector(kItalicFont), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> italic(
+ Typeface::createFromFamilies(makeSingleFamlyVector(kItalicFont), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, nullptr /* fallback */));
EXPECT_EQ(400, italic->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java, new Typeface.Builder("Family-BoldItalic.ttf").build();
- std::unique_ptr<Typeface> boldItalic(
- Typeface::createFromFamilies(makeSingleFamlyVector(kBoldItalicFont),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> boldItalic(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kBoldItalicFont), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE,
+ nullptr /* fallback */));
EXPECT_EQ(700, boldItalic->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
@@ -427,8 +431,9 @@ TEST(TypefaceTest, createFromFamilies_Family) {
std::vector<std::shared_ptr<minikin::FontFamily>> families = {
buildFamily(kRegularFont), buildFamily(kBoldFont), buildFamily(kItalicFont),
buildFamily(kBoldItalicFont)};
- std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(
- std::move(families), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> typeface(
+ Typeface::createFromFamilies(std::move(families), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, nullptr /* fallback */));
EXPECT_EQ(400, typeface->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, typeface->fStyle.slant());
}
@@ -436,10 +441,24 @@ TEST(TypefaceTest, createFromFamilies_Family) {
TEST(TypefaceTest, createFromFamilies_Family_withoutRegular) {
std::vector<std::shared_ptr<minikin::FontFamily>> families = {
buildFamily(kBoldFont), buildFamily(kItalicFont), buildFamily(kBoldItalicFont)};
- std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(
- std::move(families), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> typeface(
+ Typeface::createFromFamilies(std::move(families), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, nullptr /* fallback */));
EXPECT_EQ(700, typeface->fStyle.weight());
EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, typeface->fStyle.slant());
}
+TEST(TypefaceTest, createFromFamilies_Family_withFallback) {
+ std::vector<std::shared_ptr<minikin::FontFamily>> fallbackFamilies = {
+ buildFamily(kBoldFont), buildFamily(kItalicFont), buildFamily(kBoldItalicFont)};
+ std::unique_ptr<Typeface> fallback(
+ Typeface::createFromFamilies(std::move(fallbackFamilies), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, nullptr /* fallback */));
+ std::unique_ptr<Typeface> regular(
+ Typeface::createFromFamilies(makeSingleFamlyVector(kRegularFont), RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE, fallback.get()));
+ EXPECT_EQ(400, regular->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, regular->fStyle.slant());
+}
+
} // namespace
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 4df745ff6a20..30d0c35bcbb0 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -245,32 +245,23 @@ ASystemFontIterator* ASystemFontIterator_open() {
std::unique_ptr<ASystemFontIterator> ite(new ASystemFontIterator());
std::unordered_set<AFont, FontHasher> fonts;
- minikin::SystemFonts::getFontMap(
- [&fonts](const std::vector<std::shared_ptr<minikin::FontCollection>>& collections) {
- for (const auto& fc : collections) {
- for (uint32_t i = 0; i < fc->getFamilyCount(); ++i) {
- const auto& family = fc->getFamilyAt(i);
- for (uint32_t j = 0; j < family->getNumFonts(); ++j) {
- const minikin::Font* font = family->getFont(j);
-
- std::optional<std::string> locale;
- uint32_t localeId = font->getLocaleListId();
- if (localeId != minikin::kEmptyLocaleListId) {
- locale.emplace(minikin::getLocaleString(localeId));
- }
- std::vector<std::pair<uint32_t, float>> axes;
- for (const auto& [tag, value] : font->typeface()->GetAxes()) {
- axes.push_back(std::make_pair(tag, value));
- }
-
- fonts.insert(
- {font->typeface()->GetFontPath(), std::move(locale),
- font->style().weight(),
- font->style().slant() == minikin::FontStyle::Slant::ITALIC,
- static_cast<uint32_t>(font->typeface()->GetFontIndex()),
- axes});
- }
+ minikin::SystemFonts::getFontSet(
+ [&fonts](const std::vector<std::shared_ptr<minikin::Font>>& fontSet) {
+ for (const auto& font : fontSet) {
+ std::optional<std::string> locale;
+ uint32_t localeId = font->getLocaleListId();
+ if (localeId != minikin::kEmptyLocaleListId) {
+ locale.emplace(minikin::getLocaleString(localeId));
}
+ std::vector<std::pair<uint32_t, float>> axes;
+ for (const auto& [tag, value] : font->typeface()->GetAxes()) {
+ axes.push_back(std::make_pair(tag, value));
+ }
+
+ fonts.insert({font->typeface()->GetFontPath(), std::move(locale),
+ font->style().weight(),
+ font->style().slant() == minikin::FontStyle::Slant::ITALIC,
+ static_cast<uint32_t>(font->typeface()->GetFontIndex()), axes});
}
});
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
index 937e59493632..36361ddfe08a 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
@@ -17,7 +17,6 @@
package com.android.settingslib.spa.gallery.page
import android.os.Bundle
-import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavType
@@ -28,12 +27,14 @@ import com.android.settingslib.spa.framework.compose.toState
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
+private const val TITLE = "Sample page with arguments"
private const val STRING_PARAM_NAME = "stringParam"
private const val INT_PARAM_NAME = "intParam"
object ArgumentPageProvider : SettingsPageProvider {
- override val name = Destinations.Argument
+ override val name = "Argument"
override val arguments = listOf(
navArgument(STRING_PARAM_NAME) { type = NavType.StringType },
@@ -51,17 +52,17 @@ object ArgumentPageProvider : SettingsPageProvider {
@Composable
fun EntryItem(stringParam: String, intParam: Int) {
Preference(object : PreferenceModel {
- override val title = "Sample page with arguments"
+ override val title = TITLE
override val summary =
"$STRING_PARAM_NAME=$stringParam, $INT_PARAM_NAME=$intParam".toState()
- override val onClick = navigator("${Destinations.Argument}/$stringParam/$intParam")
+ override val onClick = navigator("$name/$stringParam/$intParam")
})
}
}
@Composable
fun ArgumentPage(stringParam: String, intParam: Int) {
- Column {
+ RegularScaffold(title = TITLE) {
Preference(object : PreferenceModel {
override val title = "String param value"
override val summary = stringParam.toState()
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
index 143c365d3a74..82005ec44c74 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
@@ -17,12 +17,8 @@
package com.android.settingslib.spa.gallery.page
import android.os.Bundle
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.api.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
@@ -30,8 +26,11 @@ import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Footer
+private const val TITLE = "Sample Footer"
+
object FooterPageProvider : SettingsPageProvider {
override val name = "Footer"
@@ -43,7 +42,7 @@ object FooterPageProvider : SettingsPageProvider {
@Composable
fun EntryItem() {
Preference(object : PreferenceModel {
- override val title = "Sample Footer"
+ override val title = TITLE
override val onClick = navigator(name)
})
}
@@ -51,7 +50,7 @@ object FooterPageProvider : SettingsPageProvider {
@Composable
private fun FooterPage() {
- Column(Modifier.verticalScroll(rememberScrollState())) {
+ RegularScaffold(title = TITLE) {
Preference(remember {
object : PreferenceModel {
override val title = "Some Preference"
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt
index ee077f4a25e6..6b7de8d29d0f 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt
@@ -31,7 +31,7 @@ import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.gallery.R
object HomePageProvider : SettingsPageProvider {
- override val name = Destinations.Home
+ override val name = "Home"
@Composable
override fun Page(arguments: Bundle?) {
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt
index 64652257c20b..cbfc60395d69 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt
@@ -18,14 +18,6 @@ package com.android.settingslib.spa.gallery.page
import com.android.settingslib.spa.framework.api.SettingsPageRepository
-object Destinations {
- const val Home = "Home"
- const val Preference = "Preference"
- const val SwitchPreference = "SwitchPreference"
- const val Argument = "Argument"
- const val Slider = "Slider"
-}
-
val galleryPageRepository = SettingsPageRepository(
allPages = listOf(
HomePageProvider,
@@ -36,5 +28,5 @@ val galleryPageRepository = SettingsPageRepository(
SettingsPagerPageProvider,
FooterPageProvider,
),
- startDestination = Destinations.Home,
+ startDestination = HomePageProvider.name,
)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt
index 8a29d35ad9d9..0463e58f09f6 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt
@@ -17,9 +17,6 @@
package com.android.settingslib.spa.gallery.page
import android.os.Bundle
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.DisabledByDefault
import androidx.compose.material.icons.outlined.TouchApp
@@ -31,7 +28,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.api.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
@@ -39,11 +35,14 @@ import com.android.settingslib.spa.framework.compose.toState
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.SettingsIcon
import kotlinx.coroutines.delay
+private const val TITLE = "Sample Preference"
+
object PreferencePageProvider : SettingsPageProvider {
- override val name = Destinations.Preference
+ override val name = "Preference"
@Composable
override fun Page(arguments: Bundle?) {
@@ -53,15 +52,15 @@ object PreferencePageProvider : SettingsPageProvider {
@Composable
fun EntryItem() {
Preference(object : PreferenceModel {
- override val title = "Sample Preference"
- override val onClick = navigator(Destinations.Preference)
+ override val title = TITLE
+ override val onClick = navigator(name)
})
}
}
@Composable
private fun PreferencePage() {
- Column(Modifier.verticalScroll(rememberScrollState())) {
+ RegularScaffold(title = TITLE) {
Preference(object : PreferenceModel {
override val title = "Preference"
})
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
index 9bcac1b84a0b..04046fa18df1 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
@@ -17,9 +17,6 @@
package com.android.settingslib.spa.gallery.page
import android.os.Bundle
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AccessAlarm
import androidx.compose.material.icons.outlined.MusicNote
@@ -29,18 +26,20 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.api.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.SettingsSlider
import com.android.settingslib.spa.widget.ui.SettingsSliderModel
+private const val TITLE = "Sample Slider"
+
object SliderPageProvider : SettingsPageProvider {
- override val name = Destinations.Slider
+ override val name = "Slider"
@Composable
override fun Page(arguments: Bundle?) {
@@ -50,15 +49,15 @@ object SliderPageProvider : SettingsPageProvider {
@Composable
fun EntryItem() {
Preference(object : PreferenceModel {
- override val title = "Sample Slider"
- override val onClick = navigator(Destinations.Slider)
+ override val title = TITLE
+ override val onClick = navigator(name)
})
}
}
@Composable
private fun SliderPage() {
- Column(Modifier.verticalScroll(rememberScrollState())) {
+ RegularScaffold(title = TITLE) {
SettingsSlider(object : SettingsSliderModel {
override val title = "Slider"
override val initValue = 40
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt
index b6f725821728..e9e5d356d2d4 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt
@@ -17,15 +17,11 @@
package com.android.settingslib.spa.gallery.page
import android.os.Bundle
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.api.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
@@ -35,10 +31,13 @@ import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import kotlinx.coroutines.delay
+private const val TITLE = "Sample SwitchPreference"
+
object SwitchPreferencePageProvider : SettingsPageProvider {
- override val name = Destinations.SwitchPreference
+ override val name = "SwitchPreference"
@Composable
override fun Page(arguments: Bundle?) {
@@ -48,15 +47,15 @@ object SwitchPreferencePageProvider : SettingsPageProvider {
@Composable
fun EntryItem() {
Preference(object : PreferenceModel {
- override val title = "Sample SwitchPreference"
- override val onClick = navigator(Destinations.SwitchPreference)
+ override val title = TITLE
+ override val onClick = navigator(name)
})
}
}
@Composable
private fun SwitchPreferencePage() {
- Column(Modifier.verticalScroll(rememberScrollState())) {
+ RegularScaffold(title = TITLE) {
SampleSwitchPreference()
SampleSwitchPreferenceWithSummary()
SampleSwitchPreferenceWithAsyncSummary()
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
index e1ca69bd7940..7d3e10768e46 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
@@ -31,4 +31,5 @@ object SettingsDimension {
end = itemPaddingEnd,
bottom = itemPaddingVertical,
)
+ val itemPaddingAround = 8.dp
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
new file mode 100644
index 000000000000..0a41a1a95936
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.scaffold
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.ArrowBack
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import com.android.settingslib.spa.framework.compose.LocalNavController
+
+@Composable
+internal fun NavigateUp() {
+ val navController = LocalNavController.current
+ val contentDescription = stringResource(
+ id = androidx.appcompat.R.string.abc_action_bar_up_description,
+ )
+ BackAction(contentDescription) {
+ navController.navigateUp()
+ }
+}
+
+@Composable
+private fun BackAction(contentDescription: String, onClick: () -> Unit) {
+ IconButton(onClick) {
+ Icon(
+ imageVector = Icons.Outlined.ArrowBack,
+ contentDescription = contentDescription,
+ )
+ }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/RegularScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/RegularScaffold.kt
new file mode 100644
index 000000000000..3325d5382f2e
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/RegularScaffold.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.scaffold
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SmallTopAppBar
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+
+/**
+ * A [Scaffold] which content is scrollable and wrapped in a [Column].
+ *
+ * For example, this is for the pages with some preferences and is scrollable when the items out of
+ * the screen.
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun RegularScaffold(
+ title: String,
+ actions: @Composable RowScope.() -> Unit = {},
+ content: @Composable () -> Unit,
+) {
+ Scaffold(
+ topBar = {
+ SmallTopAppBar(
+ title = {
+ Text(
+ text = title,
+ modifier = Modifier.padding(SettingsDimension.itemPaddingAround),
+ )
+ },
+ navigationIcon = { NavigateUp() },
+ actions = actions,
+ colors = settingsTopAppBarColors(),
+ )
+ },
+ ) { paddingValues ->
+ Column(Modifier.verticalScroll(rememberScrollState())) {
+ Spacer(Modifier.padding(paddingValues))
+ content()
+ }
+ }
+}
+
+@Composable
+internal fun settingsTopAppBarColors() = TopAppBarDefaults.largeTopAppBarColors(
+ containerColor = SettingsTheme.colorScheme.surfaceHeader,
+ scrolledContainerColor = SettingsTheme.colorScheme.surfaceHeader,
+)
+
+@Preview
+@Composable
+private fun RegularScaffoldPreview() {
+ SettingsTheme {
+ RegularScaffold(title = "Display") {}
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppOpsController.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
index 3808f64386ef..c2d85a54bc32 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppOpsController.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.framework.app
+package com.android.settingslib.spaprivileged.model.app
import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_ALLOWED
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRecord.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRecord.kt
index 8dde897cb23d..297868871389 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRecord.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRecord.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.framework.app
+package com.android.settingslib.spaprivileged.model.app
import android.content.pm.ApplicationInfo
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
index a6378ef53437..7ffa9384bfe2 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.framework.app
+package com.android.settingslib.spaprivileged.model.app
import android.content.Context
import android.content.pm.ApplicationInfo
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/Apps.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt
index f6755459c1b7..6e1afd94fe29 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/Apps.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.framework.app
+package com.android.settingslib.spaprivileged.model.app
import android.content.pm.ApplicationInfo
import android.os.UserHandle
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/PackageManagers.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt
index 66b05da03b3f..0cc497a3e899 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/PackageManagers.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/PackageManagers.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.framework.app
+package com.android.settingslib.spaprivileged.model.app
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/enterprise/EnterpriseRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/EnterpriseRepository.kt
index ae0cb772533c..fab3ae8e510b 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/enterprise/EnterpriseRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/EnterpriseRepository.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.framework.enterprise
+package com.android.settingslib.spaprivileged.model.enterprise
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 5ae514cfb524..d802b049b830 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -33,8 +33,8 @@ import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.compose.rememberDrawablePainter
import com.android.settingslib.spa.widget.ui.SettingsBody
import com.android.settingslib.spa.widget.ui.SettingsTitle
-import com.android.settingslib.spaprivileged.framework.app.PackageManagers
-import com.android.settingslib.spaprivileged.framework.app.rememberAppRepository
+import com.android.settingslib.spaprivileged.model.app.PackageManagers
+import com.android.settingslib.spaprivileged.model.app.rememberAppRepository
@Composable
fun AppInfo(packageName: String, userId: Int) {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index 57e9e9ac1b9b..430ac5409711 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -31,8 +31,8 @@ import com.android.settingslib.spa.framework.api.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.rememberContext
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
-import com.android.settingslib.spaprivileged.framework.app.AppRecord
-import com.android.settingslib.spaprivileged.framework.app.PackageManagers
+import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.model.app.PackageManagers
import kotlinx.coroutines.Dispatchers
private const val PERMISSION = "permission"
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt
index 88ad9daa85b3..3782f7cd301e 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt
@@ -20,7 +20,7 @@ import android.content.Context
import android.content.pm.ApplicationInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
-import com.android.settingslib.spaprivileged.framework.app.AppRecord
+import com.android.settingslib.spaprivileged.model.app.AppRecord
interface TogglePermissionAppListModel<T : AppRecord> {
val pageTitleResId: Int
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/WorkProfilePager.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/WorkProfilePager.kt
index 09864a17adfc..aa5ccf146d47 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/WorkProfilePager.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/WorkProfilePager.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.template.scaffold
+package com.android.settingslib.spaprivileged.template.common
import android.content.pm.UserInfo
import android.os.UserHandle
@@ -23,7 +23,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import com.android.settingslib.spa.widget.scaffold.SettingsPager
-import com.android.settingslib.spaprivileged.framework.enterprise.EnterpriseRepository
+import com.android.settingslib.spaprivileged.model.enterprise.EnterpriseRepository
@Composable
fun WorkProfilePager(content: @Composable (userInfo: UserInfo) -> Unit) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2f9bc1c59624..d75285283cbc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -54,6 +54,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
+import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
@@ -2018,12 +2019,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// in case authenticators aren't registered yet at this point:
mAuthController.addCallback(new AuthController.Callback() {
@Override
- public void onAllAuthenticatorsRegistered() {
+ public void onAllAuthenticatorsRegistered(
+ @BiometricAuthenticator.Modality int modality) {
mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE));
}
@Override
- public void onEnrollmentsChanged() {
+ public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE));
}
});
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 06e1828ef9f4..d6974dfac570 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static com.android.keyguard.LockIconView.ICON_FINGERPRINT;
@@ -29,6 +30,7 @@ import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedStateListDrawable;
+import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Process;
import android.os.VibrationAttributes;
@@ -701,13 +703,17 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
@Override
- public void onAllAuthenticatorsRegistered() {
- updateUdfpsConfig();
+ public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
+ if (modality == TYPE_FINGERPRINT) {
+ updateUdfpsConfig();
+ }
}
@Override
- public void onEnrollmentsChanged() {
- updateUdfpsConfig();
+ public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
+ if (modality == TYPE_FINGERPRINT) {
+ updateUdfpsConfig();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 47ff59cfc281..282f25104c44 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -46,6 +46,7 @@ import android.hardware.biometrics.PromptInfo;
import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
@@ -156,25 +157,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
}
};
- private final IFingerprintAuthenticatorsRegisteredCallback
- mFingerprintAuthenticatorsRegisteredCallback =
- new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
- @Override
- public void onAllAuthenticatorsRegistered(
- List<FingerprintSensorPropertiesInternal> sensors) {
- mHandler.post(() -> handleAllFingerprintAuthenticatorsRegistered(sensors));
- }
- };
-
- private final BiometricStateListener mBiometricStateListener =
- new BiometricStateListener() {
- @Override
- public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
- mHandler.post(
- () -> handleEnrollmentsChanged(userId, sensorId, hasEnrollments));
- }
- };
-
@VisibleForTesting
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -249,8 +231,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
List<FingerprintSensorPropertiesInternal> sensors) {
mExecution.assertIsMainThread();
if (DEBUG) {
- Log.d(TAG, "handleAllAuthenticatorsRegistered | sensors: " + Arrays.toString(
- sensors.toArray()));
+ Log.d(TAG, "handleAllFingerprintAuthenticatorsRegistered | sensors: "
+ + Arrays.toString(sensors.toArray()));
}
mAllFingerprintAuthenticatorsRegistered = true;
mFpProps = sensors;
@@ -292,15 +274,42 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mSidefpsController = mSidefpsControllerFactory.get();
}
- mFingerprintManager.registerBiometricStateListener(mBiometricStateListener);
+ mFingerprintManager.registerBiometricStateListener(new BiometricStateListener() {
+ @Override
+ public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
+ mHandler.post(() -> handleEnrollmentsChanged(
+ TYPE_FINGERPRINT, userId, sensorId, hasEnrollments));
+ }
+ });
updateFingerprintLocation();
for (Callback cb : mCallbacks) {
- cb.onAllAuthenticatorsRegistered();
+ cb.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT);
}
}
- private void handleEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
+ private void handleAllFaceAuthenticatorsRegistered(List<FaceSensorPropertiesInternal> sensors) {
+ mExecution.assertIsMainThread();
+ if (DEBUG) {
+ Log.d(TAG, "handleAllFaceAuthenticatorsRegistered | sensors: " + Arrays.toString(
+ sensors.toArray()));
+ }
+
+ mFaceManager.registerBiometricStateListener(new BiometricStateListener() {
+ @Override
+ public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
+ mHandler.post(() -> handleEnrollmentsChanged(
+ TYPE_FACE, userId, sensorId, hasEnrollments));
+ }
+ });
+
+ for (Callback cb : mCallbacks) {
+ cb.onAllAuthenticatorsRegistered(TYPE_FACE);
+ }
+ }
+
+ private void handleEnrollmentsChanged(@Modality int modality, int userId, int sensorId,
+ boolean hasEnrollments) {
mExecution.assertIsMainThread();
Log.d(TAG, "handleEnrollmentsChanged, userId: " + userId + ", sensorId: " + sensorId
+ ", hasEnrollments: " + hasEnrollments);
@@ -314,7 +323,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
}
}
for (Callback cb : mCallbacks) {
- cb.onEnrollmentsChanged();
+ cb.onEnrollmentsChanged(modality);
}
}
@@ -700,7 +709,26 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
if (mFingerprintManager != null) {
mFingerprintManager.addAuthenticatorsRegisteredCallback(
- mFingerprintAuthenticatorsRegisteredCallback);
+ new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FingerprintSensorPropertiesInternal> sensors) {
+ mHandler.post(() ->
+ handleAllFingerprintAuthenticatorsRegistered(sensors));
+ }
+ });
+ }
+ if (mFaceManager != null) {
+ mFaceManager.addAuthenticatorsRegisteredCallback(
+ new IFaceAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FaceSensorPropertiesInternal> sensors) {
+ mHandler.post(() ->
+ handleAllFaceAuthenticatorsRegistered(sensors));
+ }
+ }
+ );
}
mStableDisplaySize = mDisplayManager.getStableDisplaySize();
@@ -1116,13 +1144,13 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
* Called when authenticators are registered. If authenticators are already
* registered before this call, this callback will never be triggered.
*/
- default void onAllAuthenticatorsRegistered() {}
+ default void onAllAuthenticatorsRegistered(@Modality int modality) {}
/**
- * Called when UDFPS enrollments have changed. This is called after boot and on changes to
+ * Called when enrollments have changed. This is called after boot and on changes to
* enrollment.
*/
- default void onEnrollmentsChanged() {}
+ default void onEnrollmentsChanged(@Modality int modality) {}
/**
* Called when the biometric prompt starts showing.
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 38fab8ffbfad..fd3f6007d8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -308,7 +308,7 @@ class AuthRippleController @Inject constructor(
private val authControllerCallback =
object : AuthController.Callback {
- override fun onAllAuthenticatorsRegistered() {
+ override fun onAllAuthenticatorsRegistered(modality: Int) {
updateUdfpsDependentParams()
updateSensorLocation()
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index a9e310d25f9c..7da2cf150147 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -16,12 +16,15 @@
package com.android.systemui.doze;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
import static com.android.systemui.doze.DozeMachine.State.DOZE;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
+import android.hardware.biometrics.BiometricAuthenticator;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
@@ -232,13 +235,17 @@ public class DozeScreenState implements DozeMachine.Part {
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
@Override
- public void onAllAuthenticatorsRegistered() {
- updateUdfpsController();
+ public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
+ if (modality == TYPE_FINGERPRINT) {
+ updateUdfpsController();
+ }
}
@Override
- public void onEnrollmentsChanged() {
- updateUdfpsController();
+ public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
+ if (modality == TYPE_FINGERPRINT) {
+ updateUdfpsController();
+ }
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index da6c163b1eea..997a6e554364 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -16,6 +16,8 @@
package com.android.systemui.doze;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_QUICK_PICKUP;
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY;
@@ -29,6 +31,7 @@ import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
+import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.display.AmbientDisplayConfiguration;
import android.net.Uri;
import android.os.Handler;
@@ -835,13 +838,17 @@ public class DozeSensors {
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
@Override
- public void onAllAuthenticatorsRegistered() {
- updateUdfpsEnrolled();
+ public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
+ if (modality == TYPE_FINGERPRINT) {
+ updateUdfpsEnrolled();
+ }
}
@Override
- public void onEnrollmentsChanged() {
- updateUdfpsEnrolled();
+ public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
+ if (modality == TYPE_FINGERPRINT) {
+ updateUdfpsEnrolled();
+ }
}
private void updateUdfpsEnrolled() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index 948fb1428780..60380064e098 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -129,6 +129,15 @@ class QSLogger @Inject constructor(
})
}
+ fun logInternetTileUpdate(lastType: Int, callback: String) {
+ log(VERBOSE, {
+ int1 = lastType
+ str1 = callback
+ }, {
+ "mLastTileState=$int1, Callback=$str1."
+ })
+ }
+
fun logTileUpdated(tileSpec: String, state: QSTile.State) {
log(VERBOSE, {
str1 = tileSpec
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 170fecf1c8fd..ae464771bf48 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -369,11 +369,10 @@ public class InternetTile extends QSTileImpl<SignalState> {
mWifiInfo.mNoDefaultNetwork = noDefaultNetwork;
mWifiInfo.mNoValidatedNetwork = noValidatedNetwork;
mWifiInfo.mNoNetworksAvailable = noNetworksAvailable;
- if (mLastTileState == LAST_STATE_WIFI) {
- refreshState(mWifiInfo);
- } else {
- refreshState(mCellularInfo);
+ if (!noDefaultNetwork) {
+ return;
}
+ refreshState(mWifiInfo);
}
@Override
@@ -388,6 +387,7 @@ public class InternetTile extends QSTileImpl<SignalState> {
@Override
protected void handleUpdateState(SignalState state, Object arg) {
+ mQSLogger.logInternetTileUpdate(mLastTileState, arg == null ? "null" : arg.toString());
if (arg instanceof CellularCallbackInfo) {
mLastTileState = LAST_STATE_CELLULAR;
handleUpdateCellularState(state, arg);
@@ -605,4 +605,9 @@ public class InternetTile extends QSTileImpl<SignalState> {
pw.print(" "); pw.println("mLastTileState=" + mLastTileState);
pw.print(" "); pw.println("mSignalCallback=" + mSignalCallback.toString());
}
+
+ // For testing usage only.
+ protected int getLastTileState() {
+ return mLastTileState;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index c281965550e4..3e00aec8cb28 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
@@ -1006,7 +1007,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// WHEN udfps is now enrolled
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
- callback.onEnrollmentsChanged();
+ callback.onEnrollmentsChanged(TYPE_FINGERPRINT);
// THEN isUdfspEnrolled is TRUE
assertThat(mKeyguardUpdateMonitor.isUdfpsEnrolled()).isTrue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index d158892e4ec5..e0d1f7a19130 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -60,6 +60,9 @@ import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
+import android.hardware.face.FaceSensorProperties;
+import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -154,7 +157,9 @@ public class AuthControllerTest extends SysuiTestCase {
@Mock
private InteractionJankMonitor mInteractionJankMonitor;
@Captor
- ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
+ ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor;
+ @Captor
+ ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor;
@Captor
ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
@Captor
@@ -193,25 +198,38 @@ public class AuthControllerTest extends SysuiTestCase {
when(mDisplayManager.getStableDisplaySize()).thenReturn(new Point());
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
-
- final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
- componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
- "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
- "00000001" /* serialNumber */, "" /* softwareVersion */));
- componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
- "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
- "vendor/version/revision" /* softwareVersion */));
-
- FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
- 1 /* sensorId */,
- SensorProperties.STRENGTH_STRONG,
- 1 /* maxEnrollmentsPerUser */,
- componentInfo,
- FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
- true /* resetLockoutRequireHardwareAuthToken */);
- List<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- props.add(prop);
- when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+
+ final List<ComponentInfoInternal> fpComponentInfo = List.of(
+ new ComponentInfoInternal("faceSensor" /* componentId */,
+ "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
+ "00000001" /* serialNumber */, "" /* softwareVersion */));
+ final List<ComponentInfoInternal> faceComponentInfo = List.of(
+ new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
+ "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
+ "vendor/version/revision" /* softwareVersion */));
+
+ final List<FingerprintSensorPropertiesInternal> fpProps = List.of(
+ new FingerprintSensorPropertiesInternal(
+ 1 /* sensorId */,
+ SensorProperties.STRENGTH_STRONG,
+ 1 /* maxEnrollmentsPerUser */,
+ fpComponentInfo,
+ FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
+ true /* resetLockoutRequireHardwareAuthToken */));
+ when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(fpProps);
+
+ final List<FaceSensorPropertiesInternal> faceProps = List.of(
+ new FaceSensorPropertiesInternal(
+ 2 /* sensorId */,
+ SensorProperties.STRENGTH_STRONG,
+ 1 /* maxEnrollmentsPerUser */,
+ fpComponentInfo,
+ FaceSensorProperties.TYPE_RGB,
+ true /* supportsFaceDetection */,
+ true /* supportsSelfIllumination */,
+ true /* resetLockoutRequireHardwareAuthToken */));
+ when(mFaceManager.getSensorPropertiesInternal()).thenReturn(faceProps);
mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue,
mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
@@ -219,12 +237,15 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
- mAuthenticatorsRegisteredCaptor.capture());
+ mFpAuthenticatorsRegisteredCaptor.capture());
+ verify(mFaceManager).addAuthenticatorsRegisteredCallback(
+ mFaceAuthenticatorsRegisteredCaptor.capture());
when(mStatusBarStateController.isDozing()).thenReturn(false);
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
- mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
+ mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(fpProps);
+ mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(faceProps);
// Ensures that the operations posted on the handler get executed.
mTestableLooper.processAllMessages();
@@ -237,6 +258,7 @@ public class AuthControllerTest extends SysuiTestCase {
throws RemoteException {
// This test is sensitive to prior FingerprintManager interactions.
reset(mFingerprintManager);
+ reset(mFaceManager);
// This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
@@ -246,21 +268,27 @@ public class AuthControllerTest extends SysuiTestCase {
authController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
- mAuthenticatorsRegisteredCaptor.capture());
+ mFpAuthenticatorsRegisteredCaptor.capture());
+ verify(mFaceManager).addAuthenticatorsRegisteredCallback(
+ mFaceAuthenticatorsRegisteredCaptor.capture());
mTestableLooper.processAllMessages();
verify(mFingerprintManager, never()).registerBiometricStateListener(any());
+ verify(mFaceManager, never()).registerBiometricStateListener(any());
- mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>());
+ mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
+ mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
mTestableLooper.processAllMessages();
verify(mFingerprintManager).registerBiometricStateListener(any());
+ verify(mFaceManager).registerBiometricStateListener(any());
}
@Test
public void testDoesNotCrash_afterEnrollmentsChangedForUnknownSensor() throws RemoteException {
// This test is sensitive to prior FingerprintManager interactions.
reset(mFingerprintManager);
+ reset(mFaceManager);
// This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
@@ -270,18 +298,25 @@ public class AuthControllerTest extends SysuiTestCase {
authController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
- mAuthenticatorsRegisteredCaptor.capture());
+ mFpAuthenticatorsRegisteredCaptor.capture());
+ verify(mFaceManager).addAuthenticatorsRegisteredCallback(
+ mFaceAuthenticatorsRegisteredCaptor.capture());
// Emulates a device with no authenticators (empty list).
- mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>());
+ mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
+ mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
mTestableLooper.processAllMessages();
verify(mFingerprintManager).registerBiometricStateListener(
mBiometricStateCaptor.capture());
+ verify(mFaceManager).registerBiometricStateListener(
+ mBiometricStateCaptor.capture());
// Enrollments changed for an unknown sensor.
- mBiometricStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */,
- 0xbeef /* sensorId */, true /* hasEnrollments */);
+ for (BiometricStateListener listener : mBiometricStateCaptor.getAllValues()) {
+ listener.onEnrollmentsChanged(0 /* userId */,
+ 0xbeef /* sensorId */, true /* hasEnrollments */);
+ }
mTestableLooper.processAllMessages();
// Nothing should crash.
@@ -827,4 +862,3 @@ public class AuthControllerTest extends SysuiTestCase {
}
}
}
-
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 9ffc5a57cef6..b33f9a7f3933 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.doze;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP;
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
@@ -412,7 +414,7 @@ public class DozeSensorsTest extends SysuiTestCase {
// WHEN enrollment changes to TRUE
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
- mAuthControllerCallback.onEnrollmentsChanged();
+ mAuthControllerCallback.onEnrollmentsChanged(TYPE_FINGERPRINT);
// THEN mConfigured = TRUE
assertTrue(triggerSensor.mConfigured);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
index 24d051508fde..5ec6bdf3c00b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.keyguard;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.keyguard.LockIconView.ICON_LOCK;
import static com.android.keyguard.LockIconView.ICON_UNLOCK;
@@ -219,7 +221,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
Pair<Float, PointF> udfps = setupUdfps();
// WHEN all authenticators are registered
- mAuthControllerCallback.onAllAuthenticatorsRegistered();
+ mAuthControllerCallback.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT);
mDelayableExecutor.runAllReady();
// THEN lock icon view location is updated with the same coordinates as auth controller vals
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
new file mode 100644
index 000000000000..d91baa5e7fcb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
+import com.android.systemui.statusbar.connectivity.AccessPointController;
+import com.android.systemui.statusbar.connectivity.NetworkController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class InternetTileTest extends SysuiTestCase {
+
+ @Mock
+ private QSTileHost mHost;
+ @Mock
+ private NetworkController mNetworkController;
+ @Mock
+ private AccessPointController mAccessPointController;
+ @Mock
+ private InternetDialogFactory mInternetDialogFactory;
+
+ private TestableLooper mTestableLooper;
+ private InternetTile mTile;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTestableLooper = TestableLooper.get(this);
+ when(mHost.getContext()).thenReturn(mContext);
+ when(mHost.getUserContext()).thenReturn(mContext);
+
+ mTile = new InternetTile(
+ mHost,
+ mTestableLooper.getLooper(),
+ new Handler(mTestableLooper.getLooper()),
+ new FalsingManagerFake(),
+ mock(MetricsLogger.class),
+ mock(StatusBarStateController.class),
+ mock(ActivityStarter.class),
+ mock(QSLogger.class),
+ mNetworkController,
+ mAccessPointController,
+ mInternetDialogFactory
+ );
+
+ mTile.initialize();
+ mTestableLooper.processAllMessages();
+ }
+
+ @Test
+ public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
+ mTile.mSignalCallback.setConnectivityStatus(
+ /* noDefaultNetwork= */ true,
+ /* noValidatedNetwork= */ true,
+ /* noNetworksAvailable= */ true);
+ mTestableLooper.processAllMessages();
+ assertThat(String.valueOf(mTile.getState().secondaryLabel))
+ .isEqualTo(mContext.getString(R.string.quick_settings_networks_unavailable));
+ assertThat(mTile.getLastTileState()).isEqualTo(1);
+ }
+
+ @Test
+ public void setConnectivityStatus_defaultNetworkExists_notUpdateTile() {
+ mTile.mSignalCallback.setConnectivityStatus(
+ /* noDefaultNetwork= */ false,
+ /* noValidatedNetwork= */ true,
+ /* noNetworksAvailable= */ true);
+ mTestableLooper.processAllMessages();
+ assertThat(String.valueOf(mTile.getState().secondaryLabel))
+ .isNotEqualTo(mContext.getString(R.string.quick_settings_networks_unavailable));
+ assertThat(String.valueOf(mTile.getState().secondaryLabel))
+ .isNotEqualTo(mContext.getString(R.string.quick_settings_networks_available));
+ assertThat(mTile.getLastTileState()).isEqualTo(-1);
+ }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a5bcb0517d25..248e35e6964d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -63,7 +63,6 @@ import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
-import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
import static android.app.AppOpsManager._NUM_OP;
import static android.app.AppOpsManager.extractFlagsFromKey;
import static android.app.AppOpsManager.extractUidStateFromKey;
@@ -563,6 +562,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
public ArrayMap<String, Ops> pkgOps;
// true indicates there is an interested observer, false there isn't but it has such an op
+ //TODO: Move foregroundOps and hasForegroundWatchers into the AppOpsServiceInterface.
public SparseBooleanArray foregroundOps;
public boolean hasForegroundWatchers;
@@ -658,48 +658,24 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
return mode;
}
- private void evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers,
- SparseBooleanArray which) {
- boolean curValue = which.get(op, false);
- ArraySet<ModeCallback> callbacks = watchers.get(op);
- if (callbacks != null) {
- for (int cbi = callbacks.size() - 1; !curValue && cbi >= 0; cbi--) {
- if ((callbacks.valueAt(cbi).mFlags
- & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) {
- hasForegroundWatchers = true;
- curValue = true;
- }
+ public void evalForegroundOps() {
+ foregroundOps = null;
+ foregroundOps = mAppOpsServiceInterface.evalForegroundUidOps(uid, foregroundOps);
+ if (pkgOps != null) {
+ for (int i = pkgOps.size() - 1; i >= 0; i--) {
+ foregroundOps = mAppOpsServiceInterface
+ .evalForegroundPackageOps(pkgOps.valueAt(i).packageName, foregroundOps);
}
}
- which.put(op, curValue);
- }
-
- public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
- SparseBooleanArray which = null;
hasForegroundWatchers = false;
- final SparseIntArray opModes = getNonDefaultUidModes();
- for (int i = opModes.size() - 1; i >= 0; i--) {
- if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
- if (which == null) {
- which = new SparseBooleanArray();
- }
- evalForegroundWatchers(opModes.keyAt(i), watchers, which);
- }
- }
- if (pkgOps != null) {
- for (int i = pkgOps.size() - 1; i >= 0; i--) {
- Ops ops = pkgOps.valueAt(i);
- for (int j = ops.size() - 1; j >= 0; j--) {
- if (ops.valueAt(j).getMode() == AppOpsManager.MODE_FOREGROUND) {
- if (which == null) {
- which = new SparseBooleanArray();
- }
- evalForegroundWatchers(ops.keyAt(j), watchers, which);
- }
+ if (foregroundOps != null) {
+ for (int i = 0; i < foregroundOps.size(); i++) {
+ if (foregroundOps.valueAt(i)) {
+ hasForegroundWatchers = true;
+ break;
}
}
}
- foregroundOps = which;
}
}
@@ -1562,33 +1538,24 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
}
- final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
- final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>();
final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>();
final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>();
final ArrayMap<IBinder, SparseArray<StartedCallback>> mStartedWatchers = new ArrayMap<>();
final ArrayMap<IBinder, SparseArray<NotedCallback>> mNotedWatchers = new ArrayMap<>();
final AudioRestrictionManager mAudioRestrictionManager = new AudioRestrictionManager();
- final class ModeCallback implements DeathRecipient {
+ final class ModeCallback extends OnOpModeChangedListener implements DeathRecipient {
/** If mWatchedOpCode==ALL_OPS notify for ops affected by the switch-op */
public static final int ALL_OPS = -2;
- final IAppOpsCallback mCallback;
- final int mWatchingUid;
- final int mFlags;
- final int mWatchedOpCode;
- final int mCallingUid;
- final int mCallingPid;
+ // Need to keep this only because stopWatchingMode needs an IAppOpsCallback.
+ // Otherwise we can just use the IBinder object.
+ private final IAppOpsCallback mCallback;
- ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int watchedOp,
+ ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int watchedOpCode,
int callingUid, int callingPid) {
- mCallback = callback;
- mWatchingUid = watchingUid;
- mFlags = flags;
- mWatchedOpCode = watchedOp;
- mCallingUid = callingUid;
- mCallingPid = callingPid;
+ super(watchingUid, flags, watchedOpCode, callingUid, callingPid);
+ this.mCallback = callback;
try {
mCallback.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -1596,20 +1563,16 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
}
- public boolean isWatchingUid(int uid) {
- return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid;
- }
-
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("ModeCallback{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" watchinguid=");
- UserHandle.formatUid(sb, mWatchingUid);
+ UserHandle.formatUid(sb, getWatchingUid());
sb.append(" flags=0x");
- sb.append(Integer.toHexString(mFlags));
- switch (mWatchedOpCode) {
+ sb.append(Integer.toHexString(getFlags()));
+ switch (getWatchedOpCode()) {
case OP_NONE:
break;
case ALL_OPS:
@@ -1617,13 +1580,13 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
break;
default:
sb.append(" op=");
- sb.append(opToName(mWatchedOpCode));
+ sb.append(opToName(getWatchedOpCode()));
break;
}
sb.append(" from uid=");
- UserHandle.formatUid(sb, mCallingUid);
+ UserHandle.formatUid(sb, getCallingUid());
sb.append(" pid=");
- sb.append(mCallingPid);
+ sb.append(getCallingPid());
sb.append('}');
return sb.toString();
}
@@ -1636,6 +1599,11 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
public void binderDied() {
stopWatchingMode(mCallback);
}
+
+ @Override
+ public void onOpModeChanged(int op, int uid, String packageName) throws RemoteException {
+ mCallback.opChanged(op, uid, packageName);
+ }
}
final class ActiveCallback implements DeathRecipient {
@@ -1804,7 +1772,14 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
public AppOpsService(File storagePath, Handler handler, Context context) {
mContext = context;
- mAppOpsServiceInterface = new LegacyAppOpsServiceInterfaceImpl(this, this);
+
+ for (int switchedCode = 0; switchedCode < _NUM_OP; switchedCode++) {
+ int switchCode = AppOpsManager.opToSwitch(switchedCode);
+ mSwitchedOps.put(switchCode,
+ ArrayUtils.appendInt(mSwitchedOps.get(switchCode), switchedCode));
+ }
+ mAppOpsServiceInterface =
+ new LegacyAppOpsServiceInterfaceImpl(this, this, handler, context, mSwitchedOps);
LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
mFile = new AtomicFile(storagePath, "appops");
@@ -1818,12 +1793,6 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
mHandler = handler;
mConstants = new Constants(mHandler);
readState();
-
- for (int switchedCode = 0; switchedCode < _NUM_OP; switchedCode++) {
- int switchCode = AppOpsManager.opToSwitch(switchedCode);
- mSwitchedOps.put(switchCode,
- ArrayUtils.appendInt(mSwitchedOps.get(switchCode), switchedCode));
- }
}
public void publish() {
@@ -1982,20 +1951,20 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
final String[] changedPkgs = intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_PACKAGE_LIST);
for (int code : OPS_RESTRICTED_ON_SUSPEND) {
- ArraySet<ModeCallback> callbacks;
+ ArraySet<OnOpModeChangedListener> onModeChangedListeners;
synchronized (AppOpsService.this) {
- callbacks = mOpModeWatchers.get(code);
- if (callbacks == null) {
+ onModeChangedListeners =
+ mAppOpsServiceInterface.getOpModeChangedListeners(code);
+ if (onModeChangedListeners == null) {
continue;
}
- callbacks = new ArraySet<>(callbacks);
}
for (int i = 0; i < changedUids.length; i++) {
final int changedUid = changedUids[i];
final String changedPkg = changedPkgs[i];
// We trust packagemanager to insert matching uid and packageNames in the
// extras
- notifyOpChanged(callbacks, code, changedUid, changedPkg);
+ notifyOpChanged(onModeChangedListeners, code, changedUid, changedPkg);
}
}
}
@@ -2596,7 +2565,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
if (!uidState.setUidMode(code, mode)) {
return;
}
- uidState.evalForegroundOps(mOpModeWatchers);
+ uidState.evalForegroundOps();
if (mode != MODE_ERRORED && mode != previousMode) {
updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid);
}
@@ -2615,78 +2584,10 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
*/
private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
@Nullable IAppOpsCallback callbackToIgnore) {
- String[] uidPackageNames = getPackagesForUid(uid);
- ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null;
-
- synchronized (this) {
- ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
- if (callbacks != null) {
- final int callbackCount = callbacks.size();
- for (int i = 0; i < callbackCount; i++) {
- ModeCallback callback = callbacks.valueAt(i);
- if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) {
- continue;
- }
-
- ArraySet<String> changedPackages = new ArraySet<>();
- Collections.addAll(changedPackages, uidPackageNames);
- if (callbackSpecs == null) {
- callbackSpecs = new ArrayMap<>();
- }
- callbackSpecs.put(callback, changedPackages);
- }
- }
-
- for (String uidPackageName : uidPackageNames) {
- callbacks = mPackageModeWatchers.get(uidPackageName);
- if (callbacks != null) {
- if (callbackSpecs == null) {
- callbackSpecs = new ArrayMap<>();
- }
- final int callbackCount = callbacks.size();
- for (int i = 0; i < callbackCount; i++) {
- ModeCallback callback = callbacks.valueAt(i);
- if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) {
- continue;
- }
-
- ArraySet<String> changedPackages = callbackSpecs.get(callback);
- if (changedPackages == null) {
- changedPackages = new ArraySet<>();
- callbackSpecs.put(callback, changedPackages);
- }
- changedPackages.add(uidPackageName);
- }
- }
- }
-
- if (callbackSpecs != null && callbackToIgnore != null) {
- callbackSpecs.remove(mModeWatchers.get(callbackToIgnore.asBinder()));
- }
- }
-
- if (callbackSpecs == null) {
- return;
- }
-
- for (int i = 0; i < callbackSpecs.size(); i++) {
- final ModeCallback callback = callbackSpecs.keyAt(i);
- final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
- if (reportedPackageNames == null) {
- mHandler.sendMessage(PooledLambda.obtainMessage(
- AppOpsService::notifyOpChanged,
- this, callback, code, uid, (String) null));
-
- } else {
- final int reportedPackageCount = reportedPackageNames.size();
- for (int j = 0; j < reportedPackageCount; j++) {
- final String reportedPackageName = reportedPackageNames.valueAt(j);
- mHandler.sendMessage(PooledLambda.obtainMessage(
- AppOpsService::notifyOpChanged,
- this, callback, code, uid, reportedPackageName));
- }
- }
- }
+ ModeCallback listenerToIgnore = callbackToIgnore != null
+ ? mModeWatchers.get(callbackToIgnore.asBinder()) : null;
+ mAppOpsServiceInterface.notifyOpChangedForAllPkgsInUid(code, uid, onlyForeground,
+ listenerToIgnore);
}
private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
@@ -2810,7 +2711,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
return;
}
- ArraySet<ModeCallback> repCbs = null;
+ ArraySet<OnOpModeChangedListener> repCbs = null;
code = AppOpsManager.opToSwitch(code);
PackageVerificationResult pvr;
@@ -2831,16 +2732,17 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
op.setMode(mode);
if (uidState != null) {
- uidState.evalForegroundOps(mOpModeWatchers);
+ uidState.evalForegroundOps();
}
- ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code);
+ ArraySet<OnOpModeChangedListener> cbs =
+ mAppOpsServiceInterface.getOpModeChangedListeners(code);
if (cbs != null) {
if (repCbs == null) {
repCbs = new ArraySet<>();
}
repCbs.addAll(cbs);
}
- cbs = mPackageModeWatchers.get(packageName);
+ cbs = mAppOpsServiceInterface.getPackageModeChangedListeners(packageName);
if (cbs != null) {
if (repCbs == null) {
repCbs = new ArraySet<>();
@@ -2871,47 +2773,17 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
notifyOpChangedSync(code, uid, packageName, mode, previousMode);
}
- private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
+ private void notifyOpChanged(ArraySet<OnOpModeChangedListener> callbacks, int code,
int uid, String packageName) {
for (int i = 0; i < callbacks.size(); i++) {
- final ModeCallback callback = callbacks.valueAt(i);
+ final OnOpModeChangedListener callback = callbacks.valueAt(i);
notifyOpChanged(callback, code, uid, packageName);
}
}
- private void notifyOpChanged(ModeCallback callback, int code,
+ private void notifyOpChanged(OnOpModeChangedListener callback, int code,
int uid, String packageName) {
- if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
- return;
- }
-
- // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
- int[] switchedCodes;
- if (callback.mWatchedOpCode == ALL_OPS) {
- switchedCodes = mSwitchedOps.get(code);
- } else if (callback.mWatchedOpCode == OP_NONE) {
- switchedCodes = new int[]{code};
- } else {
- switchedCodes = new int[]{callback.mWatchedOpCode};
- }
-
- for (int switchedCode : switchedCodes) {
- // There are features watching for mode changes such as window manager
- // and location manager which are in our process. The callbacks in these
- // features may require permissions our remote caller does not have.
- final long identity = Binder.clearCallingIdentity();
- try {
- if (shouldIgnoreCallback(switchedCode, callback.mCallingPid,
- callback.mCallingUid)) {
- continue;
- }
- callback.mCallback.opChanged(switchedCode, uid, packageName);
- } catch (RemoteException e) {
- /* ignore */
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
+ mAppOpsServiceInterface.notifyOpChanged(callback, code, uid, packageName);
}
private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports,
@@ -2936,9 +2808,10 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
return reports;
}
- private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
- HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
- int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs) {
+ private static HashMap<OnOpModeChangedListener, ArrayList<ChangeRec>> addCallbacks(
+ HashMap<OnOpModeChangedListener, ArrayList<ChangeRec>> callbacks,
+ int op, int uid, String packageName, int previousMode,
+ ArraySet<OnOpModeChangedListener> cbs) {
if (cbs == null) {
return callbacks;
}
@@ -2947,7 +2820,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
final int N = cbs.size();
for (int i=0; i<N; i++) {
- ModeCallback cb = cbs.valueAt(i);
+ OnOpModeChangedListener cb = cbs.valueAt(i);
ArrayList<ChangeRec> reports = callbacks.get(cb);
ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName, previousMode);
if (changed != reports) {
@@ -2990,7 +2863,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
enforceManageAppOpsModes(callingPid, callingUid, reqUid);
- HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
+ HashMap<OnOpModeChangedListener, ArrayList<ChangeRec>> callbacks = null;
ArrayList<ChangeRec> allChanges = new ArrayList<>();
synchronized (this) {
boolean changed = false;
@@ -3007,9 +2880,11 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
uidState.setUidMode(code, AppOpsManager.opToDefaultMode(code));
for (String packageName : getPackagesForUid(uidState.uid)) {
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
- previousMode, mOpModeWatchers.get(code));
+ previousMode,
+ mAppOpsServiceInterface.getOpModeChangedListeners(code));
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
- previousMode, mPackageModeWatchers.get(packageName));
+ previousMode, mAppOpsServiceInterface
+ .getPackageModeChangedListeners(packageName));
allChanges = addChange(allChanges, code, uidState.uid,
packageName, previousMode);
@@ -3053,9 +2928,11 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
uidChanged = true;
final int uid = curOp.uidState.uid;
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
- previousMode, mOpModeWatchers.get(curOp.op));
+ previousMode,
+ mAppOpsServiceInterface.getOpModeChangedListeners(curOp.op));
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
- previousMode, mPackageModeWatchers.get(packageName));
+ previousMode, mAppOpsServiceInterface
+ .getPackageModeChangedListeners(packageName));
allChanges = addChange(allChanges, curOp.op, uid, packageName,
previousMode);
@@ -3075,7 +2952,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
mUidStates.remove(uidState.uid);
}
if (uidChanged) {
- uidState.evalForegroundOps(mOpModeWatchers);
+ uidState.evalForegroundOps();
}
}
@@ -3084,8 +2961,9 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
}
if (callbacks != null) {
- for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) {
- ModeCallback cb = ent.getKey();
+ for (Map.Entry<OnOpModeChangedListener, ArrayList<ChangeRec>> ent
+ : callbacks.entrySet()) {
+ OnOpModeChangedListener cb = ent.getKey();
ArrayList<ChangeRec> reports = ent.getValue();
for (int i=0; i<reports.size(); i++) {
ChangeRec rep = reports.get(i);
@@ -3121,7 +2999,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
final UidState uidState = mUidStates.valueAt(uidi);
if (uidState.foregroundOps != null) {
- uidState.evalForegroundOps(mOpModeWatchers);
+ uidState.evalForegroundOps();
}
}
}
@@ -3169,20 +3047,10 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
mModeWatchers.put(callback.asBinder(), cb);
}
if (switchOp != AppOpsManager.OP_NONE) {
- ArraySet<ModeCallback> cbs = mOpModeWatchers.get(switchOp);
- if (cbs == null) {
- cbs = new ArraySet<>();
- mOpModeWatchers.put(switchOp, cbs);
- }
- cbs.add(cb);
+ mAppOpsServiceInterface.startWatchingOpModeChanged(cb, switchOp);
}
if (mayWatchPackageName) {
- ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName);
- if (cbs == null) {
- cbs = new ArraySet<>();
- mPackageModeWatchers.put(packageName, cbs);
- }
- cbs.add(cb);
+ mAppOpsServiceInterface.startWatchingPackageModeChanged(cb, packageName);
}
evalAllForegroundOpsLocked();
}
@@ -3197,21 +3065,9 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
ModeCallback cb = mModeWatchers.remove(callback.asBinder());
if (cb != null) {
cb.unlinkToDeath();
- for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
- ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i);
- cbs.remove(cb);
- if (cbs.size() <= 0) {
- mOpModeWatchers.removeAt(i);
- }
- }
- for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
- ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i);
- cbs.remove(cb);
- if (cbs.size() <= 0) {
- mPackageModeWatchers.removeAt(i);
- }
- }
+ mAppOpsServiceInterface.removeListener(cb);
}
+
evalAllForegroundOpsLocked();
}
}
@@ -4542,12 +4398,14 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
AppOpsService::notifyOpChangedForAllPkgsInUid,
this, code, uidState.uid, true, null));
} else if (uidState.pkgOps != null) {
- final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
- if (callbacks != null) {
- for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
- final ModeCallback callback = callbacks.valueAt(cbi);
- if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
- || !callback.isWatchingUid(uidState.uid)) {
+ final ArraySet<OnOpModeChangedListener> listenerSet =
+ mAppOpsServiceInterface.getOpModeChangedListeners(code);
+ if (listenerSet != null) {
+ for (int cbi = listenerSet.size() - 1; cbi >= 0; cbi--) {
+ final OnOpModeChangedListener listener = listenerSet.valueAt(cbi);
+ if ((listener.getFlags()
+ & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
+ || !listener.isWatchingUid(uidState.uid)) {
continue;
}
for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
@@ -4558,7 +4416,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
if (op.getMode() == AppOpsManager.MODE_FOREGROUND) {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChanged,
- this, callback, code, uidState.uid,
+ this, listenerSet.valueAt(cbi), code, uidState.uid,
uidState.pkgOps.keyAt(pkgi)));
}
}
@@ -5045,7 +4903,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
}
if (changed) {
- uidState.evalForegroundOps(mOpModeWatchers);
+ uidState.evalForegroundOps();
}
}
}
@@ -5131,7 +4989,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
XmlUtils.skipCurrentTag(parser);
}
}
- uidState.evalForegroundOps(mOpModeWatchers);
+ uidState.evalForegroundOps();
}
private void readAttributionOp(TypedXmlPullParser parser, @NonNull Op parent,
@@ -6122,62 +5980,17 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
pw.println();
}
- if (mOpModeWatchers.size() > 0 && !dumpHistory) {
- boolean printedHeader = false;
- for (int i=0; i<mOpModeWatchers.size(); i++) {
- if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
- continue;
- }
- boolean printedOpHeader = false;
- ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i);
- for (int j=0; j<callbacks.size(); j++) {
- final ModeCallback cb = callbacks.valueAt(j);
- if (dumpPackage != null
- && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
- continue;
- }
- needSep = true;
- if (!printedHeader) {
- pw.println(" Op mode watchers:");
- printedHeader = true;
- }
- if (!printedOpHeader) {
- pw.print(" Op ");
- pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
- pw.println(":");
- printedOpHeader = true;
- }
- pw.print(" #"); pw.print(j); pw.print(": ");
- pw.println(cb);
- }
- }
- }
- if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
- boolean printedHeader = false;
- for (int i=0; i<mPackageModeWatchers.size(); i++) {
- if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
- continue;
- }
- needSep = true;
- if (!printedHeader) {
- pw.println(" Package mode watchers:");
- printedHeader = true;
- }
- pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
- pw.println(":");
- ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i);
- for (int j=0; j<callbacks.size(); j++) {
- pw.print(" #"); pw.print(j); pw.print(": ");
- pw.println(callbacks.valueAt(j));
- }
- }
+
+ if (!dumpHistory) {
+ needSep |= mAppOpsServiceInterface.dumpListeners(dumpOp, dumpUid, dumpPackage, pw);
}
+
if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
boolean printedHeader = false;
- for (int i=0; i<mModeWatchers.size(); i++) {
+ for (int i = 0; i < mModeWatchers.size(); i++) {
final ModeCallback cb = mModeWatchers.valueAt(i);
if (dumpPackage != null
- && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
+ && dumpUid != UserHandle.getAppId(cb.getWatchingUid())) {
continue;
}
needSep = true;
@@ -6729,16 +6542,15 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
private void notifyWatchersOfChange(int code, int uid) {
- final ArraySet<ModeCallback> clonedCallbacks;
+ final ArraySet<OnOpModeChangedListener> modeChangedListenerSet;
synchronized (this) {
- ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
- if (callbacks == null) {
+ modeChangedListenerSet = mAppOpsServiceInterface.getOpModeChangedListeners(code);
+ if (modeChangedListenerSet == null) {
return;
}
- clonedCallbacks = new ArraySet<>(callbacks);
}
- notifyOpChanged(clonedCallbacks, code, uid, null);
+ notifyOpChanged(modeChangedListenerSet, code, uid, null);
}
@Override
diff --git a/services/core/java/com/android/server/appop/AppOpsServiceInterface.java b/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
index cd5ea120f878..c707086fb2fb 100644
--- a/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
+++ b/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
@@ -14,12 +14,20 @@
* limitations under the License.
*/
package com.android.server.appop;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AppOpsManager.Mode;
+import android.util.ArraySet;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
+
+import java.io.PrintWriter;
+
/**
* Interface for accessing and modifying modes for app-ops i.e. package and uid modes.
- * In the future this interface will also include mode callbacks and op restrictions.
+ * This interface also includes functions for added and removing op mode watchers.
+ * In the future this interface will also include op restrictions.
*/
public interface AppOpsServiceInterface {
/**
@@ -95,4 +103,93 @@ public interface AppOpsServiceInterface {
* Stop tracking app-op modes for all uid and packages.
*/
void clearAllModes();
+
+ /**
+ * Registers changedListener to listen to op's mode change.
+ * @param changedListener the listener that must be trigger on the op's mode change.
+ * @param op op representing the app-op whose mode change needs to be listened to.
+ */
+ void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener, int op);
+
+ /**
+ * Registers changedListener to listen to package's app-op's mode change.
+ * @param changedListener the listener that must be trigger on the mode change.
+ * @param packageName of the package whose app-op's mode change needs to be listened to.
+ */
+ void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
+ @NonNull String packageName);
+
+ /**
+ * Stop the changedListener from triggering on any mode change.
+ * @param changedListener the listener that needs to be removed.
+ */
+ void removeListener(@NonNull OnOpModeChangedListener changedListener);
+
+ /**
+ * Temporary API which will be removed once we can safely untangle the methods that use this.
+ * Returns a set of OnOpModeChangedListener that are listening for op's mode changes.
+ * @param op app-op whose mode change is being listened to.
+ */
+ ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op);
+
+ /**
+ * Temporary API which will be removed once we can safely untangle the methods that use this.
+ * Returns a set of OnOpModeChangedListener that are listening for package's op's mode changes.
+ * @param packageName of package whose app-op's mode change is being listened to.
+ */
+ ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(@NonNull String packageName);
+
+ /**
+ * Temporary API which will be removed once we can safely untangle the methods that use this.
+ * Notify that the app-op's mode is changed by triggering the change listener.
+ * @param changedListener the change listener.
+ * @param op App-op whose mode has changed
+ * @param uid user id associated with the app-op
+ * @param packageName package name that is associated with the app-op
+ */
+ void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
+ @Nullable String packageName);
+
+ /**
+ * Temporary API which will be removed once we can safely untangle the methods that use this.
+ * Notify that the app-op's mode is changed to all packages associated with the uid by
+ * triggering the appropriate change listener.
+ * @param op App-op whose mode has changed
+ * @param uid user id associated with the app-op
+ * @param onlyForeground true if only watchers that
+ * @param callbackToIgnore callback that should be ignored.
+ */
+ void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
+ @Nullable OnOpModeChangedListener callbackToIgnore);
+
+ /**
+ * TODO: Move hasForegroundWatchers and foregroundOps into this.
+ * Go over the list of app-ops for the uid and mark app-ops with MODE_FOREGROUND in
+ * foregroundOps.
+ * @param uid for which the app-op's mode needs to be marked.
+ * @param foregroundOps boolean array where app-ops that have MODE_FOREGROUND are marked true.
+ * @return foregroundOps.
+ */
+ SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps);
+
+ /**
+ * Go over the list of app-ops for the package name and mark app-ops with MODE_FOREGROUND in
+ * foregroundOps.
+ * @param packageName for which the app-op's mode needs to be marked.
+ * @param foregroundOps boolean array where app-ops that have MODE_FOREGROUND are marked true.
+ * @return foregroundOps.
+ */
+ SparseBooleanArray evalForegroundPackageOps(String packageName,
+ SparseBooleanArray foregroundOps);
+
+ /**
+ * Dump op mode and package mode listeners and their details.
+ * @param dumpOp if -1 then op mode listeners for all app-ops are dumped. If it's set to an
+ * app-op, only the watchers for that app-op are dumped.
+ * @param dumpUid uid for which we want to dump op mode watchers.
+ * @param dumpPackage if not null and if dumpOp is -1, dumps watchers for the package name.
+ * @param printWriter writer to dump to.
+ */
+ boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage, PrintWriter printWriter);
+
}
diff --git a/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java b/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
index c27c0d3de5d7..2d498ea2117c 100644
--- a/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
+++ b/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
@@ -16,15 +16,39 @@
package com.android.server.appop;
+import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
+import static android.app.AppOpsManager.opRestrictsRead;
+
+import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
+
+import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import libcore.util.EmptyArray;
+
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.Objects;
/**
@@ -33,8 +57,13 @@ import com.android.internal.annotations.VisibleForTesting;
*/
public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface {
- // Should be the same object that the AppOpsService is using for locking.
+ static final String TAG = "LegacyAppOpsServiceInterfaceImpl";
+
+ // Must be the same object that the AppOpsService is using for locking.
final Object mLock;
+ final Handler mHandler;
+ final Context mContext;
+ final SparseArray<int[]> mSwitchedOps;
@GuardedBy("mLock")
@VisibleForTesting
@@ -43,13 +72,25 @@ public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface
@GuardedBy("mLock")
final ArrayMap<String, SparseIntArray> mPackageModes = new ArrayMap<>();
+ final SparseArray<ArraySet<OnOpModeChangedListener>> mOpModeWatchers = new SparseArray<>();
+ final ArrayMap<String, ArraySet<OnOpModeChangedListener>> mPackageModeWatchers =
+ new ArrayMap<>();
+
final PersistenceScheduler mPersistenceScheduler;
+ // Constant meaning that any UID should be matched when dispatching callbacks
+ private static final int UID_ANY = -2;
+
+
LegacyAppOpsServiceInterfaceImpl(PersistenceScheduler persistenceScheduler,
- @NonNull Object lock) {
+ @NonNull Object lock, Handler handler, Context context,
+ SparseArray<int[]> switchedOps) {
this.mPersistenceScheduler = persistenceScheduler;
this.mLock = lock;
+ this.mHandler = handler;
+ this.mContext = context;
+ this.mSwitchedOps = switchedOps;
}
@Override
@@ -158,7 +199,6 @@ public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface
}
}
-
@Override
public boolean areUidModesDefault(int uid) {
synchronized (mLock) {
@@ -195,4 +235,335 @@ public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface
}
}
-}
+ @Override
+ public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
+ int op) {
+ Objects.requireNonNull(changedListener);
+ synchronized (mLock) {
+ ArraySet<OnOpModeChangedListener> modeWatcherSet = mOpModeWatchers.get(op);
+ if (modeWatcherSet == null) {
+ modeWatcherSet = new ArraySet<>();
+ mOpModeWatchers.put(op, modeWatcherSet);
+ }
+ modeWatcherSet.add(changedListener);
+ }
+ }
+
+ @Override
+ public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
+ @NonNull String packageName) {
+ Objects.requireNonNull(changedListener);
+ Objects.requireNonNull(packageName);
+ synchronized (mLock) {
+ ArraySet<OnOpModeChangedListener> modeWatcherSet =
+ mPackageModeWatchers.get(packageName);
+ if (modeWatcherSet == null) {
+ modeWatcherSet = new ArraySet<>();
+ mPackageModeWatchers.put(packageName, modeWatcherSet);
+ }
+ modeWatcherSet.add(changedListener);
+ }
+ }
+
+ @Override
+ public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
+ Objects.requireNonNull(changedListener);
+
+ synchronized (mLock) {
+ for (int i = mOpModeWatchers.size() - 1; i >= 0; i--) {
+ ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.valueAt(i);
+ cbs.remove(changedListener);
+ if (cbs.size() <= 0) {
+ mOpModeWatchers.removeAt(i);
+ }
+ }
+
+ for (int i = mPackageModeWatchers.size() - 1; i >= 0; i--) {
+ ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.valueAt(i);
+ cbs.remove(changedListener);
+ if (cbs.size() <= 0) {
+ mPackageModeWatchers.removeAt(i);
+ }
+ }
+ }
+ }
+
+ @Override
+ public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
+ synchronized (mLock) {
+ ArraySet<OnOpModeChangedListener> modeChangedListenersSet = mOpModeWatchers.get(op);
+ if (modeChangedListenersSet == null) {
+ return new ArraySet<>();
+ }
+ return new ArraySet<>(modeChangedListenersSet);
+ }
+ }
+
+ @Override
+ public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
+ @NonNull String packageName) {
+ Objects.requireNonNull(packageName);
+
+ synchronized (mLock) {
+ ArraySet<OnOpModeChangedListener> modeChangedListenersSet =
+ mPackageModeWatchers.get(packageName);
+ if (modeChangedListenersSet == null) {
+ return new ArraySet<>();
+ }
+ return new ArraySet<>(modeChangedListenersSet);
+ }
+ }
+
+ @Override
+ public void notifyOpChanged(@NonNull OnOpModeChangedListener onModeChangedListener, int code,
+ int uid, @Nullable String packageName) {
+ Objects.requireNonNull(onModeChangedListener);
+
+ if (uid != UID_ANY && onModeChangedListener.getWatchingUid() >= 0
+ && onModeChangedListener.getWatchingUid() != uid) {
+ return;
+ }
+
+ // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
+ int[] switchedCodes;
+ if (onModeChangedListener.getWatchedOpCode() == ALL_OPS) {
+ switchedCodes = mSwitchedOps.get(code);
+ } else if (onModeChangedListener.getWatchedOpCode() == OP_NONE) {
+ switchedCodes = new int[]{code};
+ } else {
+ switchedCodes = new int[]{onModeChangedListener.getWatchedOpCode()};
+ }
+
+ for (int switchedCode : switchedCodes) {
+ // There are features watching for mode changes such as window manager
+ // and location manager which are in our process. The callbacks in these
+ // features may require permissions our remote caller does not have.
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (shouldIgnoreCallback(switchedCode, onModeChangedListener.getCallingPid(),
+ onModeChangedListener.getCallingUid())) {
+ continue;
+ }
+ onModeChangedListener.onOpModeChanged(switchedCode, uid, packageName);
+ } catch (RemoteException e) {
+ /* ignore */
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ private boolean shouldIgnoreCallback(int op, int watcherPid, int watcherUid) {
+ // If it's a restricted read op, ignore it if watcher doesn't have manage ops permission,
+ // as watcher should not use this to signal if the value is changed.
+ return opRestrictsRead(op) && mContext.checkPermission(Manifest.permission.MANAGE_APPOPS,
+ watcherPid, watcherUid) != PackageManager.PERMISSION_GRANTED;
+ }
+
+ @Override
+ public void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
+ @Nullable OnOpModeChangedListener callbackToIgnore) {
+ String[] uidPackageNames = getPackagesForUid(uid);
+ ArrayMap<OnOpModeChangedListener, ArraySet<String>> callbackSpecs = null;
+
+ synchronized (mLock) {
+ ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.get(code);
+ if (callbacks != null) {
+ final int callbackCount = callbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ OnOpModeChangedListener callback = callbacks.valueAt(i);
+
+ if (onlyForeground && (callback.getFlags()
+ & WATCH_FOREGROUND_CHANGES) == 0) {
+ continue;
+ }
+
+ ArraySet<String> changedPackages = new ArraySet<>();
+ Collections.addAll(changedPackages, uidPackageNames);
+ if (callbackSpecs == null) {
+ callbackSpecs = new ArrayMap<>();
+ }
+ callbackSpecs.put(callback, changedPackages);
+ }
+ }
+
+ for (String uidPackageName : uidPackageNames) {
+ callbacks = mPackageModeWatchers.get(uidPackageName);
+ if (callbacks != null) {
+ if (callbackSpecs == null) {
+ callbackSpecs = new ArrayMap<>();
+ }
+ final int callbackCount = callbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ OnOpModeChangedListener callback = callbacks.valueAt(i);
+
+ if (onlyForeground && (callback.getFlags()
+ & WATCH_FOREGROUND_CHANGES) == 0) {
+ continue;
+ }
+
+ ArraySet<String> changedPackages = callbackSpecs.get(callback);
+ if (changedPackages == null) {
+ changedPackages = new ArraySet<>();
+ callbackSpecs.put(callback, changedPackages);
+ }
+ changedPackages.add(uidPackageName);
+ }
+ }
+ }
+
+ if (callbackSpecs != null && callbackToIgnore != null) {
+ callbackSpecs.remove(callbackToIgnore);
+ }
+ }
+
+ if (callbackSpecs == null) {
+ return;
+ }
+
+ for (int i = 0; i < callbackSpecs.size(); i++) {
+ final OnOpModeChangedListener callback = callbackSpecs.keyAt(i);
+ final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
+ if (reportedPackageNames == null) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LegacyAppOpsServiceInterfaceImpl::notifyOpChanged,
+ this, callback, code, uid, (String) null));
+
+ } else {
+ final int reportedPackageCount = reportedPackageNames.size();
+ for (int j = 0; j < reportedPackageCount; j++) {
+ final String reportedPackageName = reportedPackageNames.valueAt(j);
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LegacyAppOpsServiceInterfaceImpl::notifyOpChanged,
+ this, callback, code, uid, reportedPackageName));
+ }
+ }
+ }
+ }
+
+ private static String[] getPackagesForUid(int uid) {
+ String[] packageNames = null;
+
+ // Very early during boot the package manager is not yet or not yet fully started. At this
+ // time there are no packages yet.
+ if (AppGlobals.getPackageManager() != null) {
+ try {
+ packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
+ }
+ if (packageNames == null) {
+ return EmptyArray.STRING;
+ }
+ return packageNames;
+ }
+
+ @Override
+ public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
+ synchronized (mLock) {
+ return evalForegroundOps(mUidModes.get(uid), foregroundOps);
+ }
+ }
+
+ @Override
+ public SparseBooleanArray evalForegroundPackageOps(String packageName,
+ SparseBooleanArray foregroundOps) {
+ synchronized (mLock) {
+ return evalForegroundOps(mPackageModes.get(packageName), foregroundOps);
+ }
+ }
+
+ private SparseBooleanArray evalForegroundOps(SparseIntArray opModes,
+ SparseBooleanArray foregroundOps) {
+ SparseBooleanArray tempForegroundOps = foregroundOps;
+ if (opModes != null) {
+ for (int i = opModes.size() - 1; i >= 0; i--) {
+ if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
+ if (tempForegroundOps == null) {
+ tempForegroundOps = new SparseBooleanArray();
+ }
+ evalForegroundWatchers(opModes.keyAt(i), tempForegroundOps);
+ }
+ }
+ }
+ return tempForegroundOps;
+ }
+
+ private void evalForegroundWatchers(int op, SparseBooleanArray foregroundOps) {
+ boolean curValue = foregroundOps.get(op, false);
+ ArraySet<OnOpModeChangedListener> listenerSet = mOpModeWatchers.get(op);
+ if (listenerSet != null) {
+ for (int cbi = listenerSet.size() - 1; !curValue && cbi >= 0; cbi--) {
+ if ((listenerSet.valueAt(cbi).getFlags()
+ & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) {
+ curValue = true;
+ }
+ }
+ }
+ foregroundOps.put(op, curValue);
+ }
+
+ @Override
+ public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
+ PrintWriter printWriter) {
+ boolean needSep = false;
+ if (mOpModeWatchers.size() > 0) {
+ boolean printedHeader = false;
+ for (int i = 0; i < mOpModeWatchers.size(); i++) {
+ if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
+ continue;
+ }
+ boolean printedOpHeader = false;
+ ArraySet<OnOpModeChangedListener> modeChangedListenerSet =
+ mOpModeWatchers.valueAt(i);
+ for (int j = 0; j < modeChangedListenerSet.size(); j++) {
+ final OnOpModeChangedListener listener = modeChangedListenerSet.valueAt(j);
+ if (dumpPackage != null
+ && dumpUid != UserHandle.getAppId(listener.getWatchingUid())) {
+ continue;
+ }
+ needSep = true;
+ if (!printedHeader) {
+ printWriter.println(" Op mode watchers:");
+ printedHeader = true;
+ }
+ if (!printedOpHeader) {
+ printWriter.print(" Op ");
+ printWriter.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
+ printWriter.println(":");
+ printedOpHeader = true;
+ }
+ printWriter.print(" #"); printWriter.print(j); printWriter.print(": ");
+ printWriter.println(listener.toString());
+ }
+ }
+ }
+
+ if (mPackageModeWatchers.size() > 0 && dumpOp < 0) {
+ boolean printedHeader = false;
+ for (int i = 0; i < mPackageModeWatchers.size(); i++) {
+ if (dumpPackage != null
+ && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
+ continue;
+ }
+ needSep = true;
+ if (!printedHeader) {
+ printWriter.println(" Package mode watchers:");
+ printedHeader = true;
+ }
+ printWriter.print(" Pkg "); printWriter.print(mPackageModeWatchers.keyAt(i));
+ printWriter.println(":");
+ ArraySet<OnOpModeChangedListener> modeChangedListenerSet =
+ mPackageModeWatchers.valueAt(i);
+
+ for (int j = 0; j < modeChangedListenerSet.size(); j++) {
+ printWriter.print(" #"); printWriter.print(j); printWriter.print(": ");
+ printWriter.println(modeChangedListenerSet.valueAt(j).toString());
+ }
+ }
+ }
+ return needSep;
+ }
+
+} \ No newline at end of file
diff --git a/services/core/java/com/android/server/appop/OnOpModeChangedListener.java b/services/core/java/com/android/server/appop/OnOpModeChangedListener.java
new file mode 100644
index 000000000000..5ebe8119f046
--- /dev/null
+++ b/services/core/java/com/android/server/appop/OnOpModeChangedListener.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.os.RemoteException;
+
+/**
+ * Listener for mode changes, encapsulates methods that should be triggered in the event of a mode
+ * change.
+ */
+abstract class OnOpModeChangedListener {
+
+ // Constant meaning that any UID should be matched when dispatching callbacks
+ private static final int UID_ANY = -2;
+
+ private int mWatchingUid;
+ private int mFlags;
+ private int mWatchedOpCode;
+ private int mCallingUid;
+ private int mCallingPid;
+
+ OnOpModeChangedListener(int watchingUid, int flags, int watchedOpCode, int callingUid,
+ int callingPid) {
+ this.mWatchingUid = watchingUid;
+ this.mFlags = flags;
+ this.mWatchedOpCode = watchedOpCode;
+ this.mCallingUid = callingUid;
+ this.mCallingPid = callingPid;
+ }
+
+ /**
+ * Returns the user id that is watching for the mode change.
+ */
+ public int getWatchingUid() {
+ return mWatchingUid;
+ }
+
+ /**
+ * Returns the flags associated with the mode change listener.
+ */
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Get the app-op whose mode change should trigger the callback.
+ */
+ public int getWatchedOpCode() {
+ return mWatchedOpCode;
+ }
+
+ /**
+ * Get the user-id that triggered the app-op mode change to be watched.
+ */
+ public int getCallingUid() {
+ return mCallingUid;
+ }
+
+ /**
+ * Get the process-id that triggered the app-op mode change to be watched.
+ */
+ public int getCallingPid() {
+ return mCallingPid;
+ }
+
+ /**
+ * returns true if the user id passed in the param is the one that is watching for op mode
+ * changed.
+ */
+ public boolean isWatchingUid(int uid) {
+ return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid;
+ }
+
+ /**
+ * Method that should be triggered when the app-op's mode is changed.
+ * @param op app-op whose mode-change is being listened to.
+ * @param uid user-is associated with the app-op.
+ * @param packageName package name associated with the app-op.
+ */
+ public abstract void onOpModeChanged(int op, int uid, String packageName)
+ throws RemoteException;
+
+ /**
+ * Return human readable string representing the listener.
+ */
+ public abstract String toString();
+
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java
new file mode 100644
index 000000000000..0f1fe68ad1d7
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.annotation.NonNull;
+import android.hardware.biometrics.SensorPropertiesInternal;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Common attributes for all biometric service providers.
+ *
+ * @param <T> Internal settings type.
+ */
+public interface BiometricServiceProvider<T extends SensorPropertiesInternal> {
+
+ /** Checks if the specified sensor is owned by this provider. */
+ boolean containsSensor(int sensorId);
+
+ /** All sensor properties. */
+ @NonNull
+ List<T> getSensorProperties();
+
+ /** Properties for the given sensor id. */
+ @NonNull
+ T getSensorProperties(int sensorId);
+
+ boolean isHardwareDetected(int sensorId);
+
+ /** If the user has any enrollments for the given sensor. */
+ boolean hasEnrollments(int sensorId, int userId);
+
+ long getAuthenticatorId(int sensorId, int userId);
+
+ @LockoutTracker.LockoutMode
+ int getLockoutModeForUser(int sensorId, int userId);
+
+ void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
+ boolean clearSchedulerBuffer);
+
+ void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
+
+ void dumpInternal(int sensorId, @NonNull PrintWriter pw);
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java
new file mode 100644
index 000000000000..4779f6f931ee
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.IBiometricAuthenticator;
+import android.hardware.biometrics.IBiometricService;
+import android.hardware.biometrics.SensorPropertiesInternal;
+import android.os.Handler;
+import android.os.IInterface;
+import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.ServiceThread;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Supplier;
+
+/**
+ * Container for all BiometricServiceProvider implementations.
+ *
+ * @param <T> The service provider type.
+ * @param <P> The internal properties type.
+ * @param <C> The registration callback for {@link #invokeRegisteredCallback(IInterface, List)}.
+ */
+public abstract class BiometricServiceRegistry<T extends BiometricServiceProvider<P>,
+ P extends SensorPropertiesInternal,
+ C extends IInterface> {
+
+ private static final String TAG = "BiometricServiceRegistry";
+
+ // Volatile so they can be read without a lock once all services are registered.
+ // But, ideally remove this and provide immutable copies via the callback instead.
+ @Nullable
+ private volatile List<T> mServiceProviders;
+ @Nullable
+ private volatile List<P> mAllProps;
+
+ @NonNull
+ private final Supplier<IBiometricService> mBiometricServiceSupplier;
+ @NonNull
+ private final RemoteCallbackList<C> mRegisteredCallbacks = new RemoteCallbackList<>();
+
+ public BiometricServiceRegistry(@NonNull Supplier<IBiometricService> biometricSupplier) {
+ mBiometricServiceSupplier = biometricSupplier;
+ }
+
+ /**
+ * Register an implementation by creating a new authenticator and initializing it via
+ * {@link IBiometricService#registerAuthenticator(int, int, int, IBiometricAuthenticator)}
+ * using the given properties.
+ *
+ * @param service service to register with
+ * @param props internal properties to initialize the authenticator
+ */
+ protected abstract void registerService(@NonNull IBiometricService service, @NonNull P props);
+
+ /**
+ * Invoke the callback to notify clients that all authenticators have been registered.
+ *
+ * @param callback callback to invoke
+ * @param allProps properties of all authenticators
+ */
+ protected abstract void invokeRegisteredCallback(@NonNull C callback,
+ @NonNull List<P> allProps) throws RemoteException;
+
+ /**
+ * Register all authenticators in a background thread.
+ *
+ * @param serviceProvider Supplier function that will be invoked on the background thread.
+ */
+ public void registerAll(Supplier<List<T>> serviceProvider) {
+ // Some HAL might not be started before the system service and will cause the code below
+ // to wait, and some of the operations below might take a significant amount of time to
+ // complete (calls to the HALs). To avoid blocking the rest of system server we put
+ // this on a background thread.
+ final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
+ true /* allowIo */);
+ thread.start();
+ final Handler handler = new Handler(thread.getLooper());
+ handler.post(() -> registerAllInBackground(serviceProvider));
+ thread.quitSafely();
+ }
+
+ /** Register authenticators now, only called by {@link #registerAll(Supplier).} */
+ @VisibleForTesting
+ public void registerAllInBackground(Supplier<List<T>> serviceProvider) {
+ List<T> providers = serviceProvider.get();
+ if (providers == null) {
+ providers = new ArrayList<>();
+ }
+
+ final IBiometricService biometricService = mBiometricServiceSupplier.get();
+ if (biometricService == null) {
+ throw new IllegalStateException("biometric service cannot be null");
+ }
+
+ // Register each sensor individually with BiometricService
+ final List<P> allProps = new ArrayList<>();
+ for (T provider : providers) {
+ final List<P> props = provider.getSensorProperties();
+ for (P prop : props) {
+ registerService(biometricService, prop);
+ }
+ allProps.addAll(props);
+ }
+
+ finishRegistration(providers, allProps);
+ }
+
+ private synchronized void finishRegistration(
+ @NonNull List<T> providers, @NonNull List<P> allProps) {
+ mServiceProviders = Collections.unmodifiableList(providers);
+ mAllProps = Collections.unmodifiableList(allProps);
+ broadcastAllAuthenticatorsRegistered();
+ }
+
+ /**
+ * Add a callback that will be invoked once the work from {@link #registerAll(Supplier)}
+ * has finished registering all providers (executes immediately if already done).
+ *
+ * @param callback registration callback
+ */
+ public synchronized void addAllRegisteredCallback(@Nullable C callback) {
+ if (callback == null) {
+ Slog.e(TAG, "addAllRegisteredCallback, callback is null");
+ return;
+ }
+
+ final boolean registered = mRegisteredCallbacks.register(callback);
+ final boolean allRegistered = mServiceProviders != null;
+ if (registered && allRegistered) {
+ broadcastAllAuthenticatorsRegistered();
+ } else if (!registered) {
+ Slog.e(TAG, "addAllRegisteredCallback failed to register callback");
+ }
+ }
+
+ private synchronized void broadcastAllAuthenticatorsRegistered() {
+ final int n = mRegisteredCallbacks.beginBroadcast();
+ for (int i = 0; i < n; ++i) {
+ final C cb = mRegisteredCallbacks.getBroadcastItem(i);
+ try {
+ invokeRegisteredCallback(cb, mAllProps);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception in broadcastAllAuthenticatorsRegistered", e);
+ } finally {
+ mRegisteredCallbacks.unregister(cb);
+ }
+ }
+ mRegisteredCallbacks.finishBroadcast();
+ }
+
+ /**
+ * Get a list of registered providers.
+ *
+ * Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
+ */
+ @NonNull
+ public List<T> getProviders() {
+ return mServiceProviders != null ? mServiceProviders : Collections.emptyList();
+ }
+
+ /**
+ * Gets the provider for given sensor id or null if not registered.
+ *
+ * Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
+ */
+ @Nullable
+ public T getProviderForSensor(int sensorId) {
+ if (mServiceProviders != null) {
+ for (T provider : mServiceProviders) {
+ if (provider.containsSensor(sensorId)) {
+ return provider;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds the provider for devices with only a single sensor.
+ *
+ * If no providers returns null. If multiple sensors are present this method
+ * will return the first one that is found (this is a legacy for test devices that
+ * use aidl/hidl concurrently and should not occur on real devices).
+ *
+ * Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
+ */
+ @Nullable
+ public Pair<Integer, T> getSingleProvider() {
+ if (mAllProps == null || mAllProps.isEmpty()) {
+ Slog.e(TAG, "No sensors found");
+ return null;
+ }
+
+ if (mAllProps.size() > 1) {
+ Slog.e(TAG, "getSingleProvider() called but multiple sensors present: "
+ + mAllProps.size());
+ }
+
+ final int sensorId = mAllProps.get(0).sensorId;
+ final T provider = getProviderForSensor(sensorId);
+ if (provider != null) {
+ return new Pair<>(sensorId, provider);
+ }
+
+ Slog.e(TAG, "Single sensor: " + sensorId + ", but provider not found");
+ return null;
+ }
+
+ /**
+ * Get the properties for all providers.
+ *
+ * Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
+ */
+ @NonNull
+ public List<P> getAllProperties() {
+ return mAllProps != null ? mAllProps : Collections.emptyList();
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
index 0d789f7a1840..f8543162f95e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
@@ -23,32 +23,64 @@ import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE;
import static android.hardware.biometrics.BiometricStateListener.STATE_KEYGUARD_AUTH;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.IBiometricStateListener;
+import android.hardware.biometrics.SensorPropertiesInternal;
import android.os.RemoteException;
+import android.os.UserManager;
import android.util.Slog;
import com.android.server.biometrics.Utils;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* A callback for receiving notifications about biometric sensor state changes.
+ *
+ * @param <T> service provider type
+ * @param <P> internal property type
*/
-public class BiometricStateCallback implements ClientMonitorCallback {
+public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
+ P extends SensorPropertiesInternal> implements ClientMonitorCallback {
private static final String TAG = "BiometricStateCallback";
@NonNull
- private final CopyOnWriteArrayList<IBiometricStateListener>
- mBiometricStateListeners = new CopyOnWriteArrayList<>();
-
- private @BiometricStateListener.State int mBiometricState;
+ private final CopyOnWriteArrayList<IBiometricStateListener> mBiometricStateListeners =
+ new CopyOnWriteArrayList<>();
+ @NonNull
+ private final UserManager mUserManager;
+ @BiometricStateListener.State
+ private int mBiometricState;
+ @NonNull
+ private List<T> mProviders = List.of();
- public BiometricStateCallback() {
+ /**
+ * Create a new callback that must be {@link #start(List)}ed.
+ *
+ * @param userManager user manager
+ */
+ public BiometricStateCallback(@NonNull UserManager userManager) {
mBiometricState = STATE_IDLE;
+ mUserManager = userManager;
+ }
+
+ /**
+ * This should be called when the service has been initialized and all providers are ready.
+ *
+ * @param allProviders all registered biometric service providers
+ */
+ public synchronized void start(@NonNull List<T> allProviders) {
+ mProviders = Collections.unmodifiableList(allProviders);
+ broadcastCurrentEnrollmentState(null /* listener */);
}
+ /** Get the current state. */
+ @BiometricStateListener.State
public int getBiometricState() {
return mBiometricState;
}
@@ -120,23 +152,43 @@ public class BiometricStateCallback implements ClientMonitorCallback {
}
/**
- * This should be invoked when:
- * 1) Enrolled --> None-enrolled
- * 2) None-enrolled --> enrolled
- * 3) HAL becomes ready
- * 4) Listener is registered
+ * Enables clients to register a BiometricStateListener. For example, this is used to forward
+ * fingerprint sensor state changes to SideFpsEventHandler.
+ *
+ * @param listener listener to register
*/
- public void notifyAllEnrollmentStateChanged(int userId, int sensorId,
+ public synchronized void registerBiometricStateListener(
+ @NonNull IBiometricStateListener listener) {
+ mBiometricStateListeners.add(listener);
+ broadcastCurrentEnrollmentState(listener);
+ }
+
+ private synchronized void broadcastCurrentEnrollmentState(
+ @Nullable IBiometricStateListener listener) {
+ for (T provider : mProviders) {
+ for (SensorPropertiesInternal prop : provider.getSensorProperties()) {
+ for (UserInfo userInfo : mUserManager.getAliveUsers()) {
+ final boolean enrolled = provider.hasEnrollments(prop.sensorId, userInfo.id);
+ if (listener != null) {
+ notifyEnrollmentStateChanged(
+ listener, userInfo.id, prop.sensorId, enrolled);
+ } else {
+ notifyAllEnrollmentStateChanged(
+ userInfo.id, prop.sensorId, enrolled);
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyAllEnrollmentStateChanged(int userId, int sensorId,
boolean hasEnrollments) {
for (IBiometricStateListener listener : mBiometricStateListeners) {
notifyEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments);
}
}
- /**
- * Notifies the listener of enrollment state changes.
- */
- public void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener,
+ private void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener,
int userId, int sensorId, boolean hasEnrollments) {
try {
listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments);
@@ -144,14 +196,4 @@ public class BiometricStateCallback implements ClientMonitorCallback {
Slog.e(TAG, "Remote exception", e);
}
}
-
- /**
- * Enables clients to register a BiometricStateListener. For example, this is used to forward
- * fingerprint sensor state changes to SideFpsEventHandler.
- *
- * @param listener
- */
- public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
- mBiometricStateListeners.add(listener);
- }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 79e65cc6d2e5..271bce9890c6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -17,20 +17,18 @@
package com.android.server.biometrics.sensors.face;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
-import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.MANAGE_FACE;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
-import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
-import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricStateListener;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
@@ -39,18 +37,18 @@ import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceServiceReceiver;
+import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.face.IFaceService;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
-import android.os.Handler;
import android.os.IBinder;
import android.os.NativeHandle;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Pair;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -58,10 +56,10 @@ import android.view.Surface;
import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
-import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -88,51 +86,10 @@ public class FaceService extends SystemService {
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final LockPatternUtils mLockPatternUtils;
@NonNull
- private final List<ServiceProvider> mServiceProviders;
-
- @Nullable
- private ServiceProvider getProviderForSensor(int sensorId) {
- for (ServiceProvider provider : mServiceProviders) {
- if (provider.containsSensor(sensorId)) {
- return provider;
- }
- }
- return null;
- }
-
- /**
- * For devices with only a single provider, returns that provider. If no providers, or multiple
- * providers exist, returns null.
- */
- @Nullable
- private Pair<Integer, ServiceProvider> getSingleProvider() {
- final List<FaceSensorPropertiesInternal> properties = getSensorProperties();
- if (properties.size() != 1) {
- Slog.e(TAG, "Multiple sensors found: " + properties.size());
- return null;
- }
-
- // Theoretically we can just return the first provider, but maybe this is easier to
- // understand.
- final int sensorId = properties.get(0).sensorId;
- for (ServiceProvider provider : mServiceProviders) {
- if (provider.containsSensor(sensorId)) {
- return new Pair<>(sensorId, provider);
- }
- }
-
- Slog.e(TAG, "Single sensor, but provider not found");
- return null;
- }
-
+ private final FaceServiceRegistry mRegistry;
@NonNull
- private List<FaceSensorPropertiesInternal> getSensorProperties() {
- final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
- for (ServiceProvider provider : mServiceProviders) {
- properties.addAll(provider.getSensorProperties());
- }
- return properties;
- }
+ private final BiometricStateCallback<ServiceProvider, FaceSensorPropertiesInternal>
+ mBiometricStateCallback;
/**
* Receives the incoming binder calls from FaceManager.
@@ -142,8 +99,7 @@ public class FaceService extends SystemService {
@Override
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId);
@@ -156,9 +112,8 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) {
-
final ProtoOutputStream proto = new ProtoOutputStream();
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider != null) {
provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer);
}
@@ -170,16 +125,14 @@ public class FaceService extends SystemService {
@Override // Binder call
public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(
String opPackageName) {
-
- return FaceService.this.getSensorProperties();
+ return mRegistry.getAllProperties();
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public FaceSensorPropertiesInternal getSensorProperties(int sensorId,
@NonNull String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId
+ ", caller: " + opPackageName);
@@ -193,8 +146,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public void generateChallenge(IBinder token, int sensorId, int userId,
IFaceServiceReceiver receiver, String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
return;
@@ -207,8 +159,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName,
long challenge) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
return;
@@ -222,8 +173,7 @@ public class FaceService extends SystemService {
public long enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
final IFaceServiceReceiver receiver, final String opPackageName,
final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for enroll");
return -1;
@@ -245,8 +195,7 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC)
@Override // Binder call
public void cancelEnrollment(final IBinder token, long requestId) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for cancelEnrollment");
return;
@@ -260,7 +209,6 @@ public class FaceService extends SystemService {
public long authenticate(final IBinder token, final long operationId, int userId,
final IFaceServiceReceiver receiver, final String opPackageName,
boolean isKeyguardBypassEnabled) {
-
// TODO(b/152413782): If the sensor supports face detect and the device is encrypted or
// lockdown, something wrong happened. See similar path in FingerprintService.
@@ -273,7 +221,7 @@ public class FaceService extends SystemService {
// permission.
final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return -1;
@@ -301,7 +249,7 @@ public class FaceService extends SystemService {
return -1;
}
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFace");
return -1;
@@ -318,8 +266,7 @@ public class FaceService extends SystemService {
IBinder token, long operationId, int userId,
IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
int cookie, boolean allowBackgroundAuthentication) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for prepareForAuthentication");
return;
@@ -336,8 +283,7 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public void startPreparedClient(int sensorId, int cookie) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for startPreparedClient");
return;
@@ -350,8 +296,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public void cancelAuthentication(final IBinder token, final String opPackageName,
final long requestId) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for cancelAuthentication");
return;
@@ -370,7 +315,7 @@ public class FaceService extends SystemService {
return;
}
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for cancelFaceDetect");
return;
@@ -383,8 +328,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public void cancelAuthenticationFromService(int sensorId, final IBinder token,
final String opPackageName, final long requestId) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
return;
@@ -397,8 +341,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public void remove(final IBinder token, final int faceId, final int userId,
final IFaceServiceReceiver receiver, final String opPackageName) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for remove");
return;
@@ -412,7 +355,6 @@ public class FaceService extends SystemService {
@Override // Binder call
public void removeAll(final IBinder token, final int userId,
final IFaceServiceReceiver receiver, final String opPackageName) {
-
final FaceServiceReceiver internalReceiver = new FaceServiceReceiver() {
int sensorsFinishedRemoving = 0;
final int numSensors = getSensorPropertiesInternal(
@@ -432,7 +374,7 @@ public class FaceService extends SystemService {
// This effectively iterates through all sensors, but has to do so by finding all
// sensors under each provider.
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
List<FaceSensorPropertiesInternal> props = provider.getSensorProperties();
for (FaceSensorPropertiesInternal prop : props) {
provider.scheduleRemoveAll(prop.sensorId, token, userId, internalReceiver,
@@ -467,27 +409,27 @@ public class FaceService extends SystemService {
try {
if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
provider.dumpProtoState(props.sensorId, proto, false);
}
}
proto.flush();
} else if (args.length > 0 && "--proto".equals(args[0])) {
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
provider.dumpProtoMetrics(props.sensorId, fd);
}
}
} else if (args.length > 1 && "--hal".equals(args[0])) {
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
provider.dumpHal(props.sensorId, fd,
Arrays.copyOfRange(args, 1, args.length, args.getClass()));
}
}
} else {
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
pw.println("Dumping for sensorId: " + props.sensorId
+ ", provider: " + provider.getClass().getSimpleName());
@@ -504,10 +446,9 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public boolean isHardwareDetected(int sensorId, String opPackageName) {
-
final long token = Binder.clearCallingIdentity();
try {
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
return false;
@@ -521,12 +462,11 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public List<Face> getEnrolledFaces(int sensorId, int userId, String opPackageName) {
-
if (userId != UserHandle.getCallingUserId()) {
Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
}
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for getEnrolledFaces, caller: " + opPackageName);
return Collections.emptyList();
@@ -538,12 +478,11 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public boolean hasEnrolledFaces(int sensorId, int userId, String opPackageName) {
-
if (userId != UserHandle.getCallingUserId()) {
Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
}
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for hasEnrolledFaces, caller: " + opPackageName);
return false;
@@ -555,8 +494,7 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for getLockoutModeForUser");
return LockoutTracker.LOCKOUT_NONE;
@@ -569,8 +507,7 @@ public class FaceService extends SystemService {
@Override
public void invalidateAuthenticatorId(int sensorId, int userId,
IInvalidationCallback callback) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for invalidateAuthenticatorId");
return;
@@ -582,7 +519,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public long getAuthenticatorId(int sensorId, int userId) {
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for getAuthenticatorId");
return 0;
@@ -595,8 +532,7 @@ public class FaceService extends SystemService {
@Override // Binder call
public void resetLockout(IBinder token, int sensorId, int userId, byte[] hardwareAuthToken,
String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
return;
@@ -610,8 +546,7 @@ public class FaceService extends SystemService {
public void setFeature(final IBinder token, int userId, int feature, boolean enabled,
final byte[] hardwareAuthToken, IFaceServiceReceiver receiver,
final String opPackageName) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for setFeature");
return;
@@ -625,8 +560,7 @@ public class FaceService extends SystemService {
@Override
public void getFeature(final IBinder token, int userId, int feature,
IFaceServiceReceiver receiver, final String opPackageName) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for getFeature");
return;
@@ -636,18 +570,14 @@ public class FaceService extends SystemService {
new ClientMonitorCallbackConverter(receiver), opPackageName);
}
- private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
- for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
- mServiceProviders.add(
- Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher));
- }
- }
+ private List<ServiceProvider> getAidlProviders() {
+ final List<ServiceProvider> providers = new ArrayList<>();
- private void addAidlProviders() {
final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
if (instances == null || instances.length == 0) {
- return;
+ return providers;
}
+
for (String instance : instances) {
final String fqName = IFace.DESCRIPTOR + "/" + instance;
final IFace face = IFace.Stub.asInterface(
@@ -660,53 +590,41 @@ public class FaceService extends SystemService {
final SensorProps[] props = face.getSensorProps();
final FaceProvider provider = new FaceProvider(getContext(), props, instance,
mLockoutResetDispatcher, BiometricContext.getInstance(getContext()));
- mServiceProviders.add(provider);
+ providers.add(provider);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
}
}
+
+ return providers;
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public void registerAuthenticators(
@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
-
- // Some HAL might not be started before the system service and will cause the code below
- // to wait, and some of the operations below might take a significant amount of time to
- // complete (calls to the HALs). To avoid blocking the rest of system server we put
- // this on a background thread.
- final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
- true /* allowIo */);
- thread.start();
- final Handler handler = new Handler(thread.getLooper());
-
- handler.post(() -> {
- addHidlProviders(hidlSensors);
- addAidlProviders();
-
- final IBiometricService biometricService = IBiometricService.Stub.asInterface(
- ServiceManager.getService(Context.BIOMETRIC_SERVICE));
-
- // Register each sensor individually with BiometricService
- for (ServiceProvider provider : mServiceProviders) {
- final List<FaceSensorPropertiesInternal> props = provider.getSensorProperties();
- for (FaceSensorPropertiesInternal prop : props) {
- final int sensorId = prop.sensorId;
- final @BiometricManager.Authenticators.Types int strength =
- Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength);
- final FaceAuthenticator authenticator = new FaceAuthenticator(
- mServiceWrapper, sensorId);
- try {
- biometricService.registerAuthenticator(sensorId, TYPE_FACE, strength,
- authenticator);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId);
- }
- }
+ mRegistry.registerAll(() -> {
+ final List<ServiceProvider> providers = new ArrayList<>();
+ for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
+ providers.add(
+ Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher));
}
+ providers.addAll(getAidlProviders());
+ return providers;
});
}
+
+ @Override
+ public void addAuthenticatorsRegisteredCallback(
+ IFaceAuthenticatorsRegisteredCallback callback) {
+ Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+ mRegistry.addAllRegisteredCallback(callback);
+ }
+
+ @Override
+ public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
+ mBiometricStateCallback.registerBiometricStateListener(listener);
+ }
}
public FaceService(Context context) {
@@ -714,7 +632,16 @@ public class FaceService extends SystemService {
mServiceWrapper = new FaceServiceWrapper();
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
- mServiceProviders = new ArrayList<>();
+ mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context));
+ mRegistry = new FaceServiceRegistry(mServiceWrapper,
+ () -> IBiometricService.Stub.asInterface(
+ ServiceManager.getService(Context.BIOMETRIC_SERVICE)));
+ mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(List<FaceSensorPropertiesInternal> sensors) {
+ mBiometricStateCallback.start(mRegistry.getProviders());
+ }
+ });
}
@Override
@@ -752,7 +679,7 @@ public class FaceService extends SystemService {
if (Utils.isVirtualEnabled(getContext())) {
Slog.i(TAG, "Sync virtual enrollments");
final int userId = ActivityManager.getCurrentUser();
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */,
true /* favorHalEnrollments */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java
new file mode 100644
index 000000000000..0f0a81d24473
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.IBiometricService;
+import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
+import android.hardware.face.IFaceService;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.BiometricServiceRegistry;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+/** Registry for {@link IFaceService} providers. */
+public class FaceServiceRegistry extends BiometricServiceRegistry<ServiceProvider,
+ FaceSensorPropertiesInternal, IFaceAuthenticatorsRegisteredCallback> {
+
+ private static final String TAG = "FaceServiceRegistry";
+
+ @NonNull
+ private final IFaceService mService;
+
+ /** Creates a new registry tied to the given service. */
+ public FaceServiceRegistry(@NonNull IFaceService service,
+ @Nullable Supplier<IBiometricService> biometricSupplier) {
+ super(biometricSupplier);
+ mService = service;
+ }
+
+ @Override
+ protected void registerService(@NonNull IBiometricService service,
+ @NonNull FaceSensorPropertiesInternal props) {
+ @BiometricManager.Authenticators.Types final int strength =
+ Utils.propertyStrengthToAuthenticatorStrength(props.sensorStrength);
+ try {
+ service.registerAuthenticator(props.sensorId, TYPE_FACE, strength,
+ new FaceAuthenticator(mService, props.sensorId));
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception when registering sensorId: " + props.sensorId);
+ }
+ }
+
+ @Override
+ protected void invokeRegisteredCallback(@NonNull IFaceAuthenticatorsRegisteredCallback callback,
+ @NonNull List<FaceSensorPropertiesInternal> allProps) throws RemoteException {
+ callback.onAllAuthenticatorsRegistered(allProps);
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 6f98365332e2..4efaedbd5530 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -26,15 +26,13 @@ import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.IBinder;
-import android.util.proto.ProtoOutputStream;
import android.view.Surface;
+import com.android.server.biometrics.sensors.BiometricServiceProvider;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.LockoutTracker;
import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.List;
/**
@@ -56,24 +54,11 @@ import java.util.List;
* to check (e.g. via {@link FaceManager#getSensorPropertiesInternal()}) that the code path isn't
* taken. ServiceProviders will provide a no-op for unsupported operations to fail safely.
*/
-public interface ServiceProvider {
- /**
- * Checks if the specified sensor is owned by this provider.
- */
- boolean containsSensor(int sensorId);
-
- @NonNull
- List<FaceSensorPropertiesInternal> getSensorProperties();
-
- @NonNull
- FaceSensorPropertiesInternal getSensorProperties(int sensorId);
+public interface ServiceProvider extends BiometricServiceProvider<FaceSensorPropertiesInternal> {
@NonNull
List<Face> getEnrolledFaces(int sensorId, int userId);
- @LockoutTracker.LockoutMode
- int getLockoutModeForUser(int sensorId, int userId);
-
/**
* Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to be
* invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
@@ -84,10 +69,6 @@ public interface ServiceProvider {
+ " this method");
}
- long getAuthenticatorId(int sensorId, int userId);
-
- boolean isHardwareDetected(int sensorId);
-
void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
@NonNull IFaceServiceReceiver receiver, String opPackageName);
@@ -142,13 +123,6 @@ public interface ServiceProvider {
void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments);
- void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
- boolean clearSchedulerBuffer);
-
- void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
-
- void dumpInternal(int sensorId, @NonNull PrintWriter pw);
-
@NonNull
ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 19d54c84c706..6bff179e8eb7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -285,6 +285,11 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
+ public boolean hasEnrollments(int sensorId, int userId) {
+ return !getEnrolledFaces(sensorId, userId).isEmpty();
+ }
+
+ @Override
public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
@NonNull IInvalidationCallback callback) {
mHandler.post(() -> {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 65289122747c..c0a119ff5f1e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -484,6 +484,11 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
@Override
+ public boolean hasEnrollments(int sensorId, int userId) {
+ return !getEnrolledFaces(sensorId, userId).isEmpty();
+ }
+
+ @Override
@LockoutTracker.LockoutMode
public int getLockoutModeForUser(int sensorId, int userId) {
return mLockoutTracker.getLockoutModeForUser(userId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 2ba449ae089e..7e2742edd47a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -17,14 +17,11 @@
package com.android.server.biometrics.sensors.fingerprint;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
-import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
-import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
import static android.Manifest.permission.TEST_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
-import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_USER_CANCELED;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
@@ -36,8 +33,6 @@ import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -65,7 +60,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
-import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -79,11 +73,9 @@ import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
-import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.log.BiometricContext;
@@ -115,74 +107,32 @@ public class FingerprintService extends SystemService {
protected static final String TAG = "FingerprintService";
- private final Object mLock = new Object();
private final AppOpsManager mAppOps;
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
private final LockPatternUtils mLockPatternUtils;
- @NonNull private final List<ServiceProvider> mServiceProviders;
- @NonNull private final BiometricStateCallback mBiometricStateCallback;
- @NonNull private final Handler mHandler;
- @NonNull private final BiometricContext mBiometricContext;
- @NonNull private final Supplier<IBiometricService> mBiometricServiceSupplier;
- @NonNull private final Function<String, IFingerprint> mIFingerprintProvider;
-
- @GuardedBy("mLock")
- @NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback>
- mAuthenticatorsRegisteredCallbacks;
-
- @GuardedBy("mLock")
- @NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps;
-
- /**
- * Registers BiometricStateListener in list stored by FingerprintService
- * @param listener new BiometricStateListener being added
- */
- public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
- mBiometricStateCallback.registerBiometricStateListener(listener);
- broadcastCurrentEnrollmentState(listener);
- }
-
- /**
- * @param listener if non-null, notifies only this listener. if null, notifies all listeners
- * in {@link BiometricStateCallback}. This is slightly ugly, but reduces
- * redundant code.
- */
- private void broadcastCurrentEnrollmentState(@Nullable IBiometricStateListener listener) {
- final UserManager um = UserManager.get(getContext());
- synchronized (mLock) {
- // Update the new listener with current state of all sensors
- for (FingerprintSensorPropertiesInternal prop : mSensorProps) {
- final ServiceProvider provider = getProviderForSensor(prop.sensorId);
- for (UserInfo userInfo : um.getAliveUsers()) {
- final boolean enrolled = !provider
- .getEnrolledFingerprints(prop.sensorId, userInfo.id).isEmpty();
-
- // Defer this work and allow the loop to release the lock sooner
- mHandler.post(() -> {
- if (listener != null) {
- mBiometricStateCallback.notifyEnrollmentStateChanged(
- listener, userInfo.id, prop.sensorId, enrolled);
- } else {
- mBiometricStateCallback.notifyAllEnrollmentStateChanged(
- userInfo.id, prop.sensorId, enrolled);
- }
- });
- }
- }
- }
- }
+ @NonNull
+ private final BiometricContext mBiometricContext;
+ @NonNull
+ private final Supplier<String[]> mAidlInstanceNameSupplier;
+ @NonNull
+ private final Function<String, IFingerprint> mIFingerprintProvider;
+ @NonNull
+ private final BiometricStateCallback<ServiceProvider, FingerprintSensorPropertiesInternal>
+ mBiometricStateCallback;
+ @NonNull
+ private final Handler mHandler;
+ @NonNull
+ private final FingerprintServiceRegistry mRegistry;
- /**
- * Receives the incoming binder calls from FingerprintManager.
- */
- private final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() {
+ /** Receives the incoming binder calls from FingerprintManager. */
+ @VisibleForTesting
+ final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() {
@android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
@Override
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId);
@@ -195,9 +145,8 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) {
-
final ProtoOutputStream proto = new ProtoOutputStream();
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider != null) {
provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer);
}
@@ -212,16 +161,14 @@ public class FingerprintService extends SystemService {
!= PackageManager.PERMISSION_GRANTED) {
Utils.checkPermission(getContext(), TEST_BIOMETRIC);
}
-
- return FingerprintService.this.getSensorProperties();
+ return mRegistry.getAllProperties();
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId,
@NonNull String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId
+ ", caller: " + opPackageName);
@@ -234,8 +181,7 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void generateChallenge(IBinder token, int sensorId, int userId,
IFingerprintServiceReceiver receiver, String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
return;
@@ -248,8 +194,7 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName,
long challenge) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
return;
@@ -264,8 +209,7 @@ public class FingerprintService extends SystemService {
public long enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken,
final int userId, final IFingerprintServiceReceiver receiver,
final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for enroll");
return -1;
@@ -278,8 +222,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_FINGERPRINT)
@Override // Binder call
public void cancelEnrollment(final IBinder token, long requestId) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for cancelEnrollment");
return;
@@ -339,10 +282,10 @@ public class FingerprintService extends SystemService {
final Pair<Integer, ServiceProvider> provider;
if (sensorId == FingerprintManager.SENSOR_ID_ANY) {
- provider = getSingleProvider();
+ provider = mRegistry.getSingleProvider();
} else {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- provider = new Pair<>(sensorId, getProviderForSensor(sensorId));
+ provider = new Pair<>(sensorId, mRegistry.getProviderForSensor(sensorId));
}
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
@@ -374,7 +317,6 @@ public class FingerprintService extends SystemService {
final IFingerprintServiceReceiver receiver,
final String opPackageName,
boolean ignoreEnrollmentState) throws PackageManager.NameNotFoundException {
-
final Context context = getUiContext();
final Context promptContext = context.createPackageContextAsUser(
opPackageName, 0 /* flags */, UserHandle.getUserHandleForUid(uId));
@@ -468,7 +410,7 @@ public class FingerprintService extends SystemService {
return -1;
}
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFingerprint");
return -1;
@@ -484,8 +426,7 @@ public class FingerprintService extends SystemService {
public void prepareForAuthentication(int sensorId, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
long requestId, int cookie, boolean allowBackgroundAuthentication) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for prepareForAuthentication");
return;
@@ -501,8 +442,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC)
@Override // Binder call
public void startPreparedClient(int sensorId, int cookie) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for startPreparedClient");
return;
@@ -532,7 +472,7 @@ public class FingerprintService extends SystemService {
return;
}
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for cancelAuthentication");
return;
@@ -553,7 +493,7 @@ public class FingerprintService extends SystemService {
// For IBiometricsFingerprint2.1, cancelling fingerprint detect is the same as
// cancelling authentication.
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for cancelFingerprintDetect");
return;
@@ -566,11 +506,9 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void cancelAuthenticationFromService(final int sensorId, final IBinder token,
final String opPackageName, final long requestId) {
-
-
Slog.d(TAG, "cancelAuthenticationFromService, sensorId: " + sensorId);
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
return;
@@ -583,8 +521,7 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void remove(final IBinder token, final int fingerId, final int userId,
final IFingerprintServiceReceiver receiver, final String opPackageName) {
-
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for remove");
return;
@@ -617,7 +554,7 @@ public class FingerprintService extends SystemService {
// This effectively iterates through all sensors, but has to do so by finding all
// sensors under each provider.
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties();
for (FingerprintSensorPropertiesInternal prop : props) {
provider.scheduleRemoveAll(prop.sensorId, token, internalReceiver, userId,
@@ -652,7 +589,7 @@ public class FingerprintService extends SystemService {
try {
if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FingerprintSensorPropertiesInternal props
: provider.getSensorProperties()) {
provider.dumpProtoState(props.sensorId, proto, false);
@@ -660,14 +597,14 @@ public class FingerprintService extends SystemService {
}
proto.flush();
} else if (args.length > 0 && "--proto".equals(args[0])) {
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FingerprintSensorPropertiesInternal props
: provider.getSensorProperties()) {
provider.dumpProtoMetrics(props.sensorId, fd);
}
}
} else {
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FingerprintSensorPropertiesInternal props
: provider.getSensorProperties()) {
pw.println("Dumping for sensorId: " + props.sensorId
@@ -698,7 +635,7 @@ public class FingerprintService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for isHardwareDetectedDeprecated, caller: "
+ opPackageName);
@@ -713,8 +650,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public boolean isHardwareDetected(int sensorId, String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
return false;
@@ -730,7 +666,7 @@ public class FingerprintService extends SystemService {
return;
}
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for rename");
return;
@@ -781,8 +717,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for hasEnrolledFingerprints, caller: " + opPackageName);
return false;
@@ -794,8 +729,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for getLockoutModeForUser");
return LockoutTracker.LOCKOUT_NONE;
@@ -807,8 +741,7 @@ public class FingerprintService extends SystemService {
@Override
public void invalidateAuthenticatorId(int sensorId, int userId,
IInvalidationCallback callback) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for invalidateAuthenticatorId");
return;
@@ -819,8 +752,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public long getAuthenticatorId(int sensorId, int userId) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for getAuthenticatorId");
return 0;
@@ -832,8 +764,7 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void resetLockout(IBinder token, int sensorId, int userId,
@Nullable byte[] hardwareAuthToken, String opPackageName) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
return;
@@ -864,55 +795,38 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void registerAuthenticators(
@NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
-
- // Some HAL might not be started before the system service and will cause the code below
- // to wait, and some of the operations below might take a significant amount of time to
- // complete (calls to the HALs). To avoid blocking the rest of system server we put
- // this on a background thread.
- final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
- true /* allowIo */);
- thread.start();
- final Handler handler = new Handler(thread.getLooper());
- handler.post(() -> {
+ mRegistry.registerAll(() -> {
+ final List<ServiceProvider> providers = new ArrayList<>();
+ providers.addAll(getHidlProviders(hidlSensors));
List<String> aidlSensors = new ArrayList<>();
- final String[] instances =
- ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
+ final String[] instances = mAidlInstanceNameSupplier.get();
if (instances != null) {
aidlSensors.addAll(Lists.newArrayList(instances));
}
- registerAuthenticatorsForService(aidlSensors, hidlSensors);
+ providers.addAll(getAidlProviders(
+ Utils.filterAvailableHalInstances(getContext(), aidlSensors)));
+ return providers;
});
- thread.quitSafely();
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void addAuthenticatorsRegisteredCallback(
IFingerprintAuthenticatorsRegisteredCallback callback) {
- if (callback == null) {
- Slog.e(TAG, "addAuthenticatorsRegisteredCallback, callback is null");
- return;
- }
+ mRegistry.addAllRegisteredCallback(callback);
+ }
- final boolean registered;
- final boolean hasSensorProps;
- synchronized (mLock) {
- registered = mAuthenticatorsRegisteredCallbacks.register(callback);
- hasSensorProps = !mSensorProps.isEmpty();
- }
- if (registered && hasSensorProps) {
- broadcastAllAuthenticatorsRegistered();
- } else if (!registered) {
- Slog.e(TAG, "addAuthenticatorsRegisteredCallback failed to register callback");
- }
+ @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
+ @Override
+ public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
+ mBiometricStateCallback.registerBiometricStateListener(listener);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void onPointerDown(long requestId, int sensorId, int x, int y,
float minor, float major) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId);
return;
@@ -923,8 +837,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void onPointerUp(long requestId, int sensorId) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId);
return;
@@ -935,8 +848,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void onUiReady(long requestId, int sensorId) {
-
- final ServiceProvider provider = getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
if (provider == null) {
Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId);
return;
@@ -947,8 +859,7 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
-
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
provider.setUdfpsOverlayController(controller);
}
}
@@ -956,22 +867,15 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void setSidefpsController(@NonNull ISidefpsController controller) {
-
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
provider.setSidefpsController(controller);
}
}
- @Override
- public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
- Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- FingerprintService.this.registerBiometricStateListener(listener);
- }
-
+ @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void onPowerPressed() {
- Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
provider.onPowerPressed();
}
}
@@ -981,6 +885,7 @@ public class FingerprintService extends SystemService {
this(context, BiometricContext.getInstance(context),
() -> IBiometricService.Stub.asInterface(
ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
+ () -> ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR),
(fqName) -> IFingerprint.Stub.asInterface(
Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName))));
}
@@ -988,61 +893,34 @@ public class FingerprintService extends SystemService {
@VisibleForTesting
FingerprintService(Context context,
BiometricContext biometricContext,
- Supplier<IBiometricService> biometricServiceProvider,
+ Supplier<IBiometricService> biometricServiceSupplier,
+ Supplier<String[]> aidlInstanceNameSupplier,
Function<String, IFingerprint> fingerprintProvider) {
super(context);
mBiometricContext = biometricContext;
- mBiometricServiceSupplier = biometricServiceProvider;
+ mAidlInstanceNameSupplier = aidlInstanceNameSupplier;
mIFingerprintProvider = fingerprintProvider;
mAppOps = context.getSystemService(AppOpsManager.class);
mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher();
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
- mServiceProviders = new ArrayList<>();
- mBiometricStateCallback = new BiometricStateCallback();
- mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
- mSensorProps = new ArrayList<>();
+ mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context));
mHandler = new Handler(Looper.getMainLooper());
+ mRegistry = new FingerprintServiceRegistry(mServiceWrapper, biometricServiceSupplier);
+ mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FingerprintSensorPropertiesInternal> sensors) {
+ mBiometricStateCallback.start(mRegistry.getProviders());
+ }
+ });
}
- @VisibleForTesting
- void registerAuthenticatorsForService(@NonNull List<String> aidlInstanceNames,
+ @NonNull
+ private List<ServiceProvider> getHidlProviders(
@NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
- addHidlProviders(hidlSensors);
- addAidlProviders(Utils.filterAvailableHalInstances(getContext(), aidlInstanceNames));
-
- final IBiometricService biometricService = mBiometricServiceSupplier.get();
-
- // Register each sensor individually with BiometricService
- for (ServiceProvider provider : mServiceProviders) {
- final List<FingerprintSensorPropertiesInternal> props =
- provider.getSensorProperties();
- for (FingerprintSensorPropertiesInternal prop : props) {
- final int sensorId = prop.sensorId;
- @BiometricManager.Authenticators.Types final int strength =
- Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength);
- final FingerprintAuthenticator authenticator = new FingerprintAuthenticator(
- mServiceWrapper, sensorId);
- try {
- biometricService.registerAuthenticator(sensorId, TYPE_FINGERPRINT,
- strength, authenticator);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId);
- }
- }
- }
-
- synchronized (mLock) {
- for (ServiceProvider provider : mServiceProviders) {
- mSensorProps.addAll(provider.getSensorProperties());
- }
- }
+ final List<ServiceProvider> providers = new ArrayList<>();
- broadcastCurrentEnrollmentState(null); // broadcasts to all listeners
- broadcastAllAuthenticatorsRegistered();
- }
-
- private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) {
for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
final Fingerprint21 fingerprint21;
if ((Build.IS_USERDEBUG || Build.IS_ENG)
@@ -1059,11 +937,16 @@ public class FingerprintService extends SystemService {
mBiometricStateCallback, hidlSensor, mHandler,
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
}
- mServiceProviders.add(fingerprint21);
+ providers.add(fingerprint21);
}
+
+ return providers;
}
- private void addAidlProviders(List<String> instances) {
+ @NonNull
+ private List<ServiceProvider> getAidlProviders(@NonNull List<String> instances) {
+ final List<ServiceProvider> providers = new ArrayList<>();
+
for (String instance : instances) {
final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
final IFingerprint fp = mIFingerprintProvider.apply(fqName);
@@ -1075,7 +958,7 @@ public class FingerprintService extends SystemService {
mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
mBiometricContext);
Slog.i(TAG, "Adding AIDL provider: " + fqName);
- mServiceProviders.add(provider);
+ providers.add(provider);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
}
@@ -1083,38 +966,8 @@ public class FingerprintService extends SystemService {
Slog.e(TAG, "Unable to get declared service: " + fqName);
}
}
- }
- // Notifies the callbacks that all of the authenticators have been registered and removes the
- // invoked callbacks from the callback list.
- private void broadcastAllAuthenticatorsRegistered() {
- // Make a local copy of the data so it can be used outside of the synchronized block when
- // making Binder calls.
- final List<IFingerprintAuthenticatorsRegisteredCallback> callbacks = new ArrayList<>();
- final List<FingerprintSensorPropertiesInternal> props;
- synchronized (mLock) {
- if (!mSensorProps.isEmpty()) {
- props = new ArrayList<>(mSensorProps);
- } else {
- Slog.e(TAG, "mSensorProps is empty");
- return;
- }
- final int n = mAuthenticatorsRegisteredCallbacks.beginBroadcast();
- for (int i = 0; i < n; ++i) {
- final IFingerprintAuthenticatorsRegisteredCallback cb =
- mAuthenticatorsRegisteredCallbacks.getBroadcastItem(i);
- callbacks.add(cb);
- mAuthenticatorsRegisteredCallbacks.unregister(cb);
- }
- mAuthenticatorsRegisteredCallbacks.finishBroadcast();
- }
- for (IFingerprintAuthenticatorsRegisteredCallback cb : callbacks) {
- try {
- cb.onAllAuthenticatorsRegistered(props);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception in onAllAuthenticatorsRegistered", e);
- }
- }
+ return providers;
}
@Override
@@ -1122,51 +975,9 @@ public class FingerprintService extends SystemService {
publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper);
}
- @Nullable
- private ServiceProvider getProviderForSensor(int sensorId) {
- for (ServiceProvider provider : mServiceProviders) {
- if (provider.containsSensor(sensorId)) {
- return provider;
- }
- }
- return null;
- }
-
- /**
- * For devices with only a single provider, returns that provider. If multiple providers,
- * returns the first one. If no providers, returns null.
- */
- @Nullable
- private Pair<Integer, ServiceProvider> getSingleProvider() {
- final List<FingerprintSensorPropertiesInternal> properties = getSensorProperties();
- if (properties.isEmpty()) {
- Slog.e(TAG, "No providers found");
- return null;
- }
-
- // Theoretically we can just return the first provider, but maybe this is easier to
- // understand.
- final int sensorId = properties.get(0).sensorId;
- for (ServiceProvider provider : mServiceProviders) {
- if (provider.containsSensor(sensorId)) {
- return new Pair<>(sensorId, provider);
- }
- }
-
- Slog.e(TAG, "Provider not found");
- return null;
- }
-
- @NonNull
- private List<FingerprintSensorPropertiesInternal> getSensorProperties() {
- synchronized (mLock) {
- return mSensorProps;
- }
- }
-
@NonNull
private List<Fingerprint> getEnrolledFingerprintsDeprecated(int userId, String opPackageName) {
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for getEnrolledFingerprintsDeprecated, caller: "
+ opPackageName);
@@ -1229,7 +1040,7 @@ public class FingerprintService extends SystemService {
if (Utils.isVirtualEnabled(getContext())) {
Slog.i(TAG, "Sync virtual enrollments");
final int userId = ActivityManager.getCurrentUser();
- for (ServiceProvider provider : mServiceProviders) {
+ for (ServiceProvider provider : mRegistry.getProviders()) {
for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) {
provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */,
true /* favorHalEnrollments */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java
new file mode 100644
index 000000000000..33810b764f23
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint;
+
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.IBiometricService;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
+import android.hardware.fingerprint.IFingerprintService;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.BiometricServiceRegistry;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+/** Registry for {@link IFingerprintService} providers. */
+public class FingerprintServiceRegistry extends BiometricServiceRegistry<ServiceProvider,
+ FingerprintSensorPropertiesInternal, IFingerprintAuthenticatorsRegisteredCallback> {
+
+ private static final String TAG = "FingerprintServiceRegistry";
+
+ @NonNull
+ private final IFingerprintService mService;
+
+ /** Creates a new registry tied to the given service. */
+ public FingerprintServiceRegistry(@NonNull IFingerprintService service,
+ @Nullable Supplier<IBiometricService> biometricSupplier) {
+ super(biometricSupplier);
+ mService = service;
+ }
+
+ @Override
+ protected void registerService(@NonNull IBiometricService service,
+ @NonNull FingerprintSensorPropertiesInternal props) {
+ @BiometricManager.Authenticators.Types final int strength =
+ Utils.propertyStrengthToAuthenticatorStrength(props.sensorStrength);
+ try {
+ service.registerAuthenticator(props.sensorId, TYPE_FINGERPRINT, strength,
+ new FingerprintAuthenticator(mService, props.sensorId));
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception when registering sensorId: " + props.sensorId);
+ }
+ }
+
+ @Override
+ protected void invokeRegisteredCallback(
+ @NonNull IFingerprintAuthenticatorsRegisteredCallback callback,
+ @NonNull List<FingerprintSensorPropertiesInternal> allProps) throws RemoteException {
+ callback.onAllAuthenticatorsRegistered(allProps);
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index 275d7e445a75..9075e7ec2080 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -28,14 +28,11 @@ import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
-import android.util.proto.ProtoOutputStream;
+import com.android.server.biometrics.sensors.BiometricServiceProvider;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.LockoutTracker;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.List;
/**
@@ -59,23 +56,8 @@ import java.util.List;
* fail safely.
*/
@SuppressWarnings("deprecation")
-public interface ServiceProvider {
- /**
- * Checks if the specified sensor is owned by this provider.
- */
- boolean containsSensor(int sensorId);
-
- @NonNull
- List<FingerprintSensorPropertiesInternal> getSensorProperties();
-
- /**
- * Returns the internal properties of the specified sensor, if owned by this provider.
- *
- * @param sensorId The ID of a fingerprint sensor, or -1 for any sensor.
- * @return An object representing the internal properties of the specified sensor.
- */
- @Nullable
- FingerprintSensorPropertiesInternal getSensorProperties(int sensorId);
+public interface ServiceProvider extends
+ BiometricServiceProvider<FingerprintSensorPropertiesInternal> {
void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken);
@@ -126,16 +108,11 @@ public interface ServiceProvider {
void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments);
- boolean isHardwareDetected(int sensorId);
-
void rename(int sensorId, int fingerId, int userId, @NonNull String name);
@NonNull
List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId);
- @LockoutTracker.LockoutMode
- int getLockoutModeForUser(int sensorId, int userId);
-
/**
* Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to
* be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
@@ -143,7 +120,6 @@ public interface ServiceProvider {
void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
@NonNull IInvalidationCallback callback);
- long getAuthenticatorId(int sensorId, int userId);
void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major);
@@ -161,13 +137,6 @@ public interface ServiceProvider {
*/
void setSidefpsController(@NonNull ISidefpsController controller);
- void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
- boolean clearSchedulerBuffer);
-
- void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
-
- void dumpInternal(int sensorId, @NonNull PrintWriter pw);
-
@NonNull
ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 2dc005206b42..3fe6332fcaa0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -565,6 +565,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
@Override
+ public boolean hasEnrollments(int sensorId, int userId) {
+ return !getEnrolledFingerprints(sensorId, userId).isEmpty();
+ }
+
+ @Override
public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
@NonNull IInvalidationCallback callback) {
mHandler.post(() -> {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index ed482f013869..0e6df8e0df77 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -789,6 +789,11 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
@Override
+ public boolean hasEnrollments(int sensorId, int userId) {
+ return !getEnrolledFingerprints(sensorId, userId).isEmpty();
+ }
+
+ @Override
@LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) {
return mLockoutTracker.getLockoutModeForUser(userId);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 5731af68df95..297439f33a8b 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -315,4 +315,10 @@ public abstract class UserManagerInternal {
/** TODO(b/239982558): add javadoc / mention invalid_id is used to unassing */
public abstract void assignUserToDisplay(@UserIdInt int userId, int displayId);
+
+ /**
+ * Returns {@code true} if the user is visible (as defined by
+ * {@link UserManager#isUserVisible()} in the given display.
+ */
+ public abstract boolean isUserVisible(@UserIdInt int userId, int displayId);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 87ab87df0b0c..e423ea9170d7 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -7005,7 +7005,12 @@ public class UserManagerService extends IUserManager.Stub {
mUsersOnSecondaryDisplays.put(userId, displayId);
}
}
- }
+
+ @Override
+ public boolean isUserVisible(int userId, int displayId) {
+ return isUserVisibleOnDisplay(userId, displayId);
+ }
+ } // class LocalService
/**
* Check if user has restrictions
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index df902c2916ba..fe4aa534df6f 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -657,7 +657,7 @@ public class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStat
// Now that we have finally received all the data, we can tell mStats about it.
synchronized (mStats) {
- mStats.recordHistoryEventLocked(
+ mStats.addHistoryEventLocked(
elapsedRealtime,
uptime,
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 37643c3c6f6f..202beb377b2c 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -108,7 +108,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsHistory;
-import com.android.internal.os.BatteryStatsHistory.HistoryStepDetailsCalculator;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderTransactionNameResolver;
@@ -174,6 +173,7 @@ public class BatteryStatsImpl extends BatteryStats {
private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
private static final boolean DEBUG_BINDER_STATS = false;
private static final boolean DEBUG_MEMORY = false;
+ private static final boolean DEBUG_HISTORY = false;
// TODO: remove "tcp" from network methods, since we measure total stats.
@@ -322,11 +322,6 @@ public class BatteryStatsImpl extends BatteryStats {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
- @NonNull
- BatteryStatsHistory copyHistory() {
- return mHistory.copy();
- }
-
@VisibleForTesting
public final class UidToRemove {
private final int mStartUid;
@@ -418,7 +413,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (changed) {
final long uptimeMs = mClock.uptimeMillis();
final long elapsedRealtimeMs = mClock.elapsedRealtime();
- mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -673,16 +668,16 @@ public class BatteryStatsImpl extends BatteryStats {
/**
* Mapping isolated uids to the actual owning app uid.
*/
- private final SparseIntArray mIsolatedUids = new SparseIntArray();
+ final SparseIntArray mIsolatedUids = new SparseIntArray();
/**
* Internal reference count of isolated uids.
*/
- private final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
+ final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
/**
* The statistics we have collected organized by uids.
*/
- private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
+ final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
// A set of pools of currently active timers. When a timer is queried, we will divide the
// elapsed time by the number of active timers to arrive at that timer's share of the time.
@@ -690,21 +685,20 @@ public class BatteryStatsImpl extends BatteryStats {
// changes.
@VisibleForTesting
protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
- private final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
- private final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
- private final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
- new SparseArray<>();
- private final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
- private final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
+ final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
+ final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
+ final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
+ final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
+ final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
// Last partial timers we use for distributing CPU usage.
@VisibleForTesting
@@ -719,24 +713,69 @@ public class BatteryStatsImpl extends BatteryStats {
protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
private boolean mSystemReady;
- private boolean mShuttingDown;
-
- private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
- private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator =
- new HistoryStepDetailsCalculatorImpl();
-
- private boolean mHaveBatteryLevel = false;
- private boolean mBatteryPluggedIn;
- private int mBatteryStatus;
- private int mBatteryLevel;
- private int mBatteryPlugType;
- private int mBatteryChargeUah;
- private int mBatteryHealth;
- private int mBatteryTemperature;
- private int mBatteryVoltageMv = -1;
+ boolean mShuttingDown;
+
+ final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
+
+ long mHistoryBaseTimeMs;
+ protected boolean mHaveBatteryLevel = false;
+ protected boolean mRecordingHistory = false;
+ int mNumHistoryItems;
+
+ private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
+ private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024;
+
+ final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
+ private SparseArray<HistoryTag> mHistoryTags;
+ final Parcel mHistoryBuffer = Parcel.obtain();
+ final HistoryItem mHistoryLastWritten = new HistoryItem();
+ final HistoryItem mHistoryLastLastWritten = new HistoryItem();
+ final HistoryItem mHistoryAddTmp = new HistoryItem();
+ int mNextHistoryTagIdx = 0;
+ int mNumHistoryTagChars = 0;
+ int mHistoryBufferLastPos = -1;
+ int mActiveHistoryStates = 0xffffffff;
+ int mActiveHistoryStates2 = 0xffffffff;
+ long mLastHistoryElapsedRealtimeMs = 0;
+ long mTrackRunningHistoryElapsedRealtimeMs = 0;
+ long mTrackRunningHistoryUptimeMs = 0;
@NonNull
- private final BatteryStatsHistory mHistory;
+ final BatteryStatsHistory mBatteryStatsHistory;
+
+ final HistoryItem mHistoryCur = new HistoryItem();
+
+ // Used by computeHistoryStepDetails
+ HistoryStepDetails mLastHistoryStepDetails = null;
+ byte mLastHistoryStepLevel = 0;
+ final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
+
+ /**
+ * Total time (in milliseconds) spent executing in user code.
+ */
+ long mLastStepCpuUserTimeMs;
+ long mCurStepCpuUserTimeMs;
+ /**
+ * Total time (in milliseconds) spent executing in kernel code.
+ */
+ long mLastStepCpuSystemTimeMs;
+ long mCurStepCpuSystemTimeMs;
+ /**
+ * Times from /proc/stat (but measured in milliseconds).
+ */
+ long mLastStepStatUserTimeMs;
+ long mLastStepStatSystemTimeMs;
+ long mLastStepStatIOWaitTimeMs;
+ long mLastStepStatIrqTimeMs;
+ long mLastStepStatSoftIrqTimeMs;
+ long mLastStepStatIdleTimeMs;
+ long mCurStepStatUserTimeMs;
+ long mCurStepStatSystemTimeMs;
+ long mCurStepStatIOWaitTimeMs;
+ long mCurStepStatIrqTimeMs;
+ long mCurStepStatSoftIrqTimeMs;
+ long mCurStepStatIdleTimeMs;
private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
@@ -1352,6 +1391,7 @@ public class BatteryStatsImpl extends BatteryStats {
int mDischargeUnplugLevel;
int mDischargePlugLevel;
int mDischargeCurrentLevel;
+ int mCurrentBatteryLevel;
int mLowDischargeAmountSinceCharge;
int mHighDischargeAmountSinceCharge;
int mDischargeScreenOnUnplugLevel;
@@ -1403,6 +1443,7 @@ public class BatteryStatsImpl extends BatteryStats {
private int mNumConnectivityChange;
+ private int mBatteryVoltageMv = -1;
private int mEstimatedBatteryCapacityMah = -1;
private int mLastLearnedBatteryCapacityUah = -1;
@@ -1586,27 +1627,28 @@ public class BatteryStatsImpl extends BatteryStats {
}
public BatteryStatsImpl(Clock clock) {
- this(clock, null);
+ this(clock, (File) null);
}
public BatteryStatsImpl(Clock clock, File historyDirectory) {
init(clock);
- mHandler = null;
- mConstants = new Constants(mHandler);
mStartClockTimeMs = clock.currentTimeMillis();
mCheckinFile = null;
mDailyFile = null;
if (historyDirectory == null) {
mStatsFile = null;
- mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
+ mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
} else {
mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
- mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES,
- mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
+ mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, historyDirectory,
+ this::getMaxHistoryFiles);
}
+ mHandler = null;
mPlatformIdleStateCallback = null;
mMeasuredEnergyRetriever = null;
mUserInfoProvider = null;
+ mConstants = new Constants(mHandler);
+ clearHistoryLocked();
}
private void init(Clock clock) {
@@ -3869,188 +3911,406 @@ public class BatteryStatsImpl extends BatteryStats {
return kmt;
}
- private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator {
- private final HistoryStepDetails mDetails = new HistoryStepDetails();
-
- private boolean mHasHistoryStepDetails;
+ /**
+ * Returns the index for the specified tag. If this is the first time the tag is encountered
+ * while writing the current history buffer, the method returns
+ * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
+ */
+ private int writeHistoryTag(HistoryTag tag) {
+ if (tag.string == null) {
+ Slog.wtfStack(TAG, "writeHistoryTag called with null name");
+ }
+
+ final int stringLength = tag.string.length();
+ if (stringLength > MAX_HISTORY_TAG_STRING_LENGTH) {
+ Slog.e(TAG, "Long battery history tag: " + tag.string);
+ tag.string = tag.string.substring(0, MAX_HISTORY_TAG_STRING_LENGTH);
+ }
+
+ Integer idxObj = mHistoryTagPool.get(tag);
+ int idx;
+ if (idxObj != null) {
+ idx = idxObj;
+ if ((idx & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ mHistoryTagPool.put(tag, idx & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
+ }
+ return idx;
+ } else if (mNextHistoryTagIdx < HISTORY_TAG_INDEX_LIMIT) {
+ idx = mNextHistoryTagIdx;
+ HistoryTag key = new HistoryTag();
+ key.setTo(tag);
+ tag.poolIdx = idx;
+ mHistoryTagPool.put(key, idx);
+ mNextHistoryTagIdx++;
+
+ mNumHistoryTagChars += stringLength + 1;
+ if (mHistoryTags != null) {
+ mHistoryTags.put(idx, key);
+ }
+ return idx | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
+ } else {
+ // Tag pool overflow: include the tag itself in the parcel
+ return HISTORY_TAG_INDEX_LIMIT | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
+ }
+ }
- private int mLastHistoryStepLevel;
+ /*
+ The history delta format uses flags to denote further data in subsequent ints in the parcel.
+
+ There is always the first token, which may contain the delta time, or an indicator of
+ the length of the time (int or long) following this token.
+
+ First token: always present,
+ 31 23 15 7 0
+ █M|L|K|J|I|H|G|F█E|D|C|B|A|T|T|T█T|T|T|T|T|T|T|T█T|T|T|T|T|T|T|T█
+
+ T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
+ follows containing the time, and 0x7ffff indicates a long immediately follows with the
+ delta time.
+ A: battery level changed and an int follows with battery data.
+ B: state changed and an int follows with state change data.
+ C: state2 has changed and an int follows with state2 change data.
+ D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
+ E: event data has changed and an event struct follows.
+ F: battery charge in coulombs has changed and an int with the charge follows.
+ G: state flag denoting that the mobile radio was active.
+ H: state flag denoting that the wifi radio was active.
+ I: state flag denoting that a wifi scan occurred.
+ J: state flag denoting that a wifi full lock was held.
+ K: state flag denoting that the gps was on.
+ L: state flag denoting that a wakelock was held.
+ M: state flag denoting that the cpu was running.
+
+ Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
+ with the time delta.
+
+ Battery level int: if A in the first token is set,
+ 31 23 15 7 0
+ █L|L|L|L|L|L|L|T█T|T|T|T|T|T|T|T█T|V|V|V|V|V|V|V█V|V|V|V|V|V|V|D█
+
+ D: indicates that extra history details follow.
+ V: the battery voltage.
+ T: the battery temperature.
+ L: the battery level (out of 100).
+
+ State change int: if B in the first token is set,
+ 31 23 15 7 0
+ █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
+
+ A: wifi multicast was on.
+ B: battery was plugged in.
+ C: screen was on.
+ D: phone was scanning for signal.
+ E: audio was on.
+ F: a sensor was active.
+
+ State2 change int: if C in the first token is set,
+ 31 23 15 7 0
+ █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
+
+ A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
+ B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
+ C: a bluetooth scan was active.
+ D: the camera was active.
+ E: bluetooth was on.
+ F: a phone call was active.
+ G: the device was charging.
+ H: 2 bits indicating the device-idle (doze) state: off, light, full
+ I: the flashlight was on.
+ J: wifi was on.
+ K: wifi was running.
+ L: video was playing.
+ M: power save mode was on.
+
+ Wakelock/wakereason struct: if D in the first token is set,
+ TODO(adamlesinski): describe wakelock/wakereason struct.
+
+ Event struct: if E in the first token is set,
+ TODO(adamlesinski): describe the event struct.
+
+ History step details struct: if D in the battery level int is set,
+ TODO(adamlesinski): describe the history step details struct.
+
+ Battery charge int: if F in the first token is set, an int representing the battery charge
+ in coulombs follows.
+ */
- /**
- * Total time (in milliseconds) spent executing in user code.
- */
- private long mLastStepCpuUserTimeMs;
- private long mCurStepCpuUserTimeMs;
- /**
- * Total time (in milliseconds) spent executing in kernel code.
- */
- private long mLastStepCpuSystemTimeMs;
- private long mCurStepCpuSystemTimeMs;
- /**
- * Times from /proc/stat (but measured in milliseconds).
- */
- private long mLastStepStatUserTimeMs;
- private long mLastStepStatSystemTimeMs;
- private long mLastStepStatIOWaitTimeMs;
- private long mLastStepStatIrqTimeMs;
- private long mLastStepStatSoftIrqTimeMs;
- private long mLastStepStatIdleTimeMs;
- private long mCurStepStatUserTimeMs;
- private long mCurStepStatSystemTimeMs;
- private long mCurStepStatIOWaitTimeMs;
- private long mCurStepStatIrqTimeMs;
- private long mCurStepStatSoftIrqTimeMs;
- private long mCurStepStatIdleTimeMs;
-
- @Override
- public HistoryStepDetails getHistoryStepDetails() {
- if (mBatteryLevel >= mLastHistoryStepLevel && mHasHistoryStepDetails) {
- mLastHistoryStepLevel = mBatteryLevel;
- return null;
- }
+ @GuardedBy("this")
+ public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
+ if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
+ dest.writeInt(BatteryStatsHistory.DELTA_TIME_ABS);
+ cur.writeToParcel(dest, 0);
+ return;
+ }
- // Perform a CPU update right after we do this collection, so we have started
- // collecting good data for the next step.
- requestImmediateCpuUpdate();
+ final long deltaTime = cur.time - last.time;
+ final int lastBatteryLevelInt = buildBatteryLevelInt(last);
+ final int lastStateInt = buildStateInt(last);
- if (mPlatformIdleStateCallback != null) {
- mDetails.statSubsystemPowerState =
- mPlatformIdleStateCallback.getSubsystemLowPowerStats();
- if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
- mDetails.statSubsystemPowerState);
- }
-
- if (!mHasHistoryStepDetails) {
- // We are not generating a delta, so all we need to do is reset the stats
- // we will later be doing a delta from.
- final int uidCount = mUidStats.size();
- for (int i = 0; i < uidCount; i++) {
- final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
- uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
- }
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
- mDetails.clear();
+ int deltaTimeToken;
+ if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
+ deltaTimeToken = BatteryStatsHistory.DELTA_TIME_LONG;
+ } else if (deltaTime >= BatteryStatsHistory.DELTA_TIME_ABS) {
+ deltaTimeToken = BatteryStatsHistory.DELTA_TIME_INT;
+ } else {
+ deltaTimeToken = (int)deltaTime;
+ }
+ int firstToken = deltaTimeToken | (cur.states & BatteryStatsHistory.DELTA_STATE_MASK);
+ final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
+ ? BatteryStatsHistory.BATTERY_DELTA_LEVEL_FLAG : 0;
+ final boolean computeStepDetails = includeStepDetails != 0
+ || mLastHistoryStepDetails == null;
+ final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
+ final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
+ if (batteryLevelIntChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_BATTERY_LEVEL_FLAG;
+ }
+ final int stateInt = buildStateInt(cur);
+ final boolean stateIntChanged = stateInt != lastStateInt;
+ if (stateIntChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_STATE_FLAG;
+ }
+ final boolean state2IntChanged = cur.states2 != last.states2;
+ if (state2IntChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG;
+ }
+ if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+ firstToken |= BatteryStatsHistory.DELTA_WAKELOCK_FLAG;
+ }
+ if (cur.eventCode != HistoryItem.EVENT_NONE) {
+ firstToken |= BatteryStatsHistory.DELTA_EVENT_FLAG;
+ }
+
+ final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
+ if (batteryChargeChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_BATTERY_CHARGE_FLAG;
+ }
+ dest.writeInt(firstToken);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
+ + " deltaTime=" + deltaTime);
+
+ if (deltaTimeToken >= BatteryStatsHistory.DELTA_TIME_INT) {
+ if (deltaTimeToken == BatteryStatsHistory.DELTA_TIME_INT) {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
+ dest.writeInt((int)deltaTime);
} else {
- if (DEBUG) {
- Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
- + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
- + " irq=" + mLastStepStatIrqTimeMs + " sirq="
- + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
- Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
- + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
- + " irq=" + mCurStepStatIrqTimeMs + " sirq="
- + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
- }
- mDetails.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
- mDetails.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
- mDetails.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
- mDetails.statSystemTime =
- (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
- mDetails.statIOWaitTime =
- (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
- mDetails.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
- mDetails.statSoftIrqTime =
- (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
- mDetails.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
- mDetails.appCpuUid1 = mDetails.appCpuUid2 = mDetails.appCpuUid3 = -1;
- mDetails.appCpuUTime1 = mDetails.appCpuUTime2 = mDetails.appCpuUTime3 = 0;
- mDetails.appCpuSTime1 = mDetails.appCpuSTime2 = mDetails.appCpuSTime3 = 0;
- final int uidCount = mUidStats.size();
- for (int i = 0; i < uidCount; i++) {
- final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- final int totalUTimeMs =
- (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
- final int totalSTimeMs =
- (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
- final int totalTimeMs = totalUTimeMs + totalSTimeMs;
- uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
- uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
- if (totalTimeMs <= (mDetails.appCpuUTime3 + mDetails.appCpuSTime3)) {
- continue;
- }
- if (totalTimeMs <= (mDetails.appCpuUTime2 + mDetails.appCpuSTime2)) {
- mDetails.appCpuUid3 = uid.mUid;
- mDetails.appCpuUTime3 = totalUTimeMs;
- mDetails.appCpuSTime3 = totalSTimeMs;
- } else {
- mDetails.appCpuUid3 = mDetails.appCpuUid2;
- mDetails.appCpuUTime3 = mDetails.appCpuUTime2;
- mDetails.appCpuSTime3 = mDetails.appCpuSTime2;
- if (totalTimeMs <= (mDetails.appCpuUTime1 + mDetails.appCpuSTime1)) {
- mDetails.appCpuUid2 = uid.mUid;
- mDetails.appCpuUTime2 = totalUTimeMs;
- mDetails.appCpuSTime2 = totalSTimeMs;
- } else {
- mDetails.appCpuUid2 = mDetails.appCpuUid1;
- mDetails.appCpuUTime2 = mDetails.appCpuUTime1;
- mDetails.appCpuSTime2 = mDetails.appCpuSTime1;
- mDetails.appCpuUid1 = uid.mUid;
- mDetails.appCpuUTime1 = totalUTimeMs;
- mDetails.appCpuSTime1 = totalSTimeMs;
- }
- }
- }
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
+ dest.writeLong(deltaTime);
+ }
+ }
+ if (batteryLevelIntChanged) {
+ dest.writeInt(batteryLevelInt);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
+ + Integer.toHexString(batteryLevelInt)
+ + " batteryLevel=" + cur.batteryLevel
+ + " batteryTemp=" + cur.batteryTemperature
+ + " batteryVolt=" + (int)cur.batteryVoltage);
+ }
+ if (stateIntChanged) {
+ dest.writeInt(stateInt);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
+ + Integer.toHexString(stateInt)
+ + " batteryStatus=" + cur.batteryStatus
+ + " batteryHealth=" + cur.batteryHealth
+ + " batteryPlugType=" + cur.batteryPlugType
+ + " states=0x" + Integer.toHexString(cur.states));
+ }
+ if (state2IntChanged) {
+ dest.writeInt(cur.states2);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
+ + Integer.toHexString(cur.states2));
+ }
+ if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+ int wakeLockIndex;
+ int wakeReasonIndex;
+ if (cur.wakelockTag != null) {
+ wakeLockIndex = writeHistoryTag(cur.wakelockTag);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+ + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+ } else {
+ wakeLockIndex = 0xffff;
+ }
+ if (cur.wakeReasonTag != null) {
+ wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+ + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+ } else {
+ wakeReasonIndex = 0xffff;
+ }
+ dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
+ if (cur.wakelockTag != null
+ && (wakeLockIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ cur.wakelockTag.writeToParcel(dest, 0);
+ cur.tagsFirstOccurrence = true;
+ }
+ if (cur.wakeReasonTag != null
+ && (wakeReasonIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ cur.wakeReasonTag.writeToParcel(dest, 0);
+ cur.tagsFirstOccurrence = true;
}
-
- mHasHistoryStepDetails = mBatteryLevel <= mLastHistoryStepLevel;
- mLastHistoryStepLevel = mBatteryLevel;
-
- return mDetails;
}
-
- public void addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
- int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
- int statSoftIrqTimeMs, int statIdleTimeMs) {
- if (DEBUG) {
- Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
- + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
- + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
- + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
+ if (cur.eventCode != HistoryItem.EVENT_NONE) {
+ final int index = writeHistoryTag(cur.eventTag);
+ final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
+ dest.writeInt(codeAndIndex);
+ if ((index & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ cur.eventTag.writeToParcel(dest, 0);
+ cur.tagsFirstOccurrence = true;
}
- mCurStepCpuUserTimeMs += totalUTimeMs;
- mCurStepCpuSystemTimeMs += totalSTimeMs;
- mCurStepStatUserTimeMs += statUserTimeMs;
- mCurStepStatSystemTimeMs += statSystemTimeMs;
- mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
- mCurStepStatIrqTimeMs += statIrqTimeMs;
- mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
- mCurStepStatIdleTimeMs += statIdleTimeMs;
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
+ + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
+ + cur.eventTag.string);
}
+ if (computeStepDetails) {
+ if (mPlatformIdleStateCallback != null) {
+ mCurHistoryStepDetails.statSubsystemPowerState =
+ mPlatformIdleStateCallback.getSubsystemLowPowerStats();
+ if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
+ mCurHistoryStepDetails.statSubsystemPowerState);
- @Override
- public void clear() {
- mHasHistoryStepDetails = false;
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
+ }
+ computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
+ if (includeStepDetails != 0) {
+ mCurHistoryStepDetails.writeToParcel(dest);
+ }
+ cur.stepDetails = mCurHistoryStepDetails;
+ mLastHistoryStepDetails = mCurHistoryStepDetails;
+ } else {
+ cur.stepDetails = null;
+ }
+ if (mLastHistoryStepLevel < cur.batteryLevel) {
+ mLastHistoryStepDetails = null;
+ }
+ mLastHistoryStepLevel = cur.batteryLevel;
+
+ if (batteryChargeChanged) {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
+ dest.writeInt(cur.batteryChargeUah);
+ }
+ dest.writeDouble(cur.modemRailChargeMah);
+ dest.writeDouble(cur.wifiRailChargeMah);
+ }
+
+ private int buildBatteryLevelInt(HistoryItem h) {
+ return ((((int)h.batteryLevel)<<25)&0xfe000000)
+ | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
+ | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
+ }
+
+ private int buildStateInt(HistoryItem h) {
+ int plugType = 0;
+ if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
+ plugType = 1;
+ } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
+ plugType = 2;
+ } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
+ plugType = 3;
+ }
+ return ((h.batteryStatus & BatteryStatsHistory.STATE_BATTERY_STATUS_MASK)
+ << BatteryStatsHistory.STATE_BATTERY_STATUS_SHIFT)
+ | ((h.batteryHealth & BatteryStatsHistory.STATE_BATTERY_HEALTH_MASK)
+ << BatteryStatsHistory.STATE_BATTERY_HEALTH_SHIFT)
+ | ((plugType & BatteryStatsHistory.STATE_BATTERY_PLUG_MASK)
+ << BatteryStatsHistory.STATE_BATTERY_PLUG_SHIFT)
+ | (h.states & (~BatteryStatsHistory.STATE_BATTERY_MASK));
+ }
+
+ private void computeHistoryStepDetails(final HistoryStepDetails out,
+ final HistoryStepDetails last) {
+ final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
+
+ // Perform a CPU update right after we do this collection, so we have started
+ // collecting good data for the next step.
+ requestImmediateCpuUpdate();
+
+ if (last == null) {
+ // We are not generating a delta, so all we need to do is reset the stats
+ // we will later be doing a delta from.
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
+ uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
+ }
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
+ tmp.clear();
+ return;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
+ + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
+ + " irq=" + mLastStepStatIrqTimeMs + " sirq="
+ + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
+ Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
+ + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
+ + " irq=" + mCurStepStatIrqTimeMs + " sirq="
+ + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
+ }
+ out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
+ out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
+ out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
+ out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
+ out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
+ out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
+ out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
+ out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
+ out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
+ out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
+ out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
+ final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
+ final int totalTimeMs = totalUTimeMs + totalSTimeMs;
+ uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
+ uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
+ if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) {
+ continue;
+ }
+ if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) {
+ out.appCpuUid3 = uid.mUid;
+ out.appCpuUTime3 = totalUTimeMs;
+ out.appCpuSTime3 = totalSTimeMs;
+ } else {
+ out.appCpuUid3 = out.appCpuUid2;
+ out.appCpuUTime3 = out.appCpuUTime2;
+ out.appCpuSTime3 = out.appCpuSTime2;
+ if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) {
+ out.appCpuUid2 = uid.mUid;
+ out.appCpuUTime2 = totalUTimeMs;
+ out.appCpuSTime2 = totalSTimeMs;
+ } else {
+ out.appCpuUid2 = out.appCpuUid1;
+ out.appCpuUTime2 = out.appCpuUTime1;
+ out.appCpuSTime2 = out.appCpuSTime1;
+ out.appCpuUid1 = uid.mUid;
+ out.appCpuUTime1 = totalUTimeMs;
+ out.appCpuSTime1 = totalSTimeMs;
+ }
+ }
}
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
}
@GuardedBy("this")
@Override
public void commitCurrentHistoryBatchLocked() {
- mHistory.commitCurrentHistoryBatchLocked();
+ mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
}
@GuardedBy("this")
@@ -4066,9 +4326,191 @@ public class BatteryStatsImpl extends BatteryStats {
}
@GuardedBy("this")
- public void recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
+ void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+ if (!mHaveBatteryLevel || !mRecordingHistory) {
+ return;
+ }
+
+ final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
+ final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
+ final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
+ final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
+ final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
+ if (DEBUG) {
+ Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
+ + Integer.toHexString(diffStates) + " lastDiff="
+ + Integer.toHexString(lastDiffStates) + " diff2="
+ + Integer.toHexString(diffStates2) + " lastDiff2="
+ + Integer.toHexString(lastDiffStates2));
+ }
+ if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
+ && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
+ && (diffStates2&lastDiffStates2) == 0
+ && (!mHistoryLastWritten.tagsFirstOccurrence && !cur.tagsFirstOccurrence)
+ && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
+ && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
+ && mHistoryLastWritten.stepDetails == null
+ && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
+ || cur.eventCode == HistoryItem.EVENT_NONE)
+ && mHistoryLastWritten.batteryLevel == cur.batteryLevel
+ && mHistoryLastWritten.batteryStatus == cur.batteryStatus
+ && mHistoryLastWritten.batteryHealth == cur.batteryHealth
+ && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
+ && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
+ && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
+ // We can merge this new change in with the last one. Merging is
+ // allowed as long as only the states have changed, and within those states
+ // as long as no bit has changed both between now and the last entry, as
+ // well as the last entry and the one before it (so we capture any toggles).
+ if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
+ mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
+ mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
+ mHistoryBufferLastPos = -1;
+ elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
+ // If the last written history had a wakelock tag, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have a wakelock tag.
+ if (mHistoryLastWritten.wakelockTag != null) {
+ cur.wakelockTag = cur.localWakelockTag;
+ cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
+ }
+ // If the last written history had a wake reason tag, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have a wakelock tag.
+ if (mHistoryLastWritten.wakeReasonTag != null) {
+ cur.wakeReasonTag = cur.localWakeReasonTag;
+ cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
+ }
+ // If the last written history had an event, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have an event.
+ if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
+ cur.eventCode = mHistoryLastWritten.eventCode;
+ cur.eventTag = cur.localEventTag;
+ cur.eventTag.setTo(mHistoryLastWritten.eventTag);
+ }
+ mHistoryLastWritten.setTo(mHistoryLastLastWritten);
+ }
+ final int dataSize = mHistoryBuffer.dataSize();
+
+ if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
+ //open a new history file.
+ final long start = SystemClock.uptimeMillis();
+ writeHistoryLocked();
+ if (DEBUG) {
+ Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
+ + (SystemClock.uptimeMillis() - start));
+ }
+ mBatteryStatsHistory.startNextFile();
+ mHistoryBuffer.setDataSize(0);
+ mHistoryBuffer.setDataPosition(0);
+ mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
+ mHistoryBufferLastPos = -1;
+ mHistoryLastWritten.clear();
+ mHistoryLastLastWritten.clear();
+
+ // Mark every entry in the pool with a flag indicating that the tag
+ // has not yet been encountered while writing the current history buffer.
+ for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
+ entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
+ }
+ // Make a copy of mHistoryCur.
+ HistoryItem copy = new HistoryItem();
+ copy.setTo(cur);
+ // startRecordingHistory will reset mHistoryCur.
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
+ // Add the copy into history buffer.
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, copy);
+ return;
+ }
+
+ if (dataSize == 0) {
+ // The history is currently empty; we need it to start with a time stamp.
+ cur.currentTime = mClock.currentTimeMillis();
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
+ }
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
+ }
+
+ @GuardedBy("this")
+ private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
+ if (mBatteryStatsHistoryIterator != null) {
+ throw new IllegalStateException("Can't do this while iterating history!");
+ }
+ mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
+ mHistoryLastLastWritten.setTo(mHistoryLastWritten);
+ final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
+ mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
+ mHistoryLastWritten.tagsFirstOccurrence = hasTags;
+ mHistoryLastWritten.states &= mActiveHistoryStates;
+ mHistoryLastWritten.states2 &= mActiveHistoryStates2;
+ writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
+ mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+ cur.wakelockTag = null;
+ cur.wakeReasonTag = null;
+ cur.eventCode = HistoryItem.EVENT_NONE;
+ cur.eventTag = null;
+ cur.tagsFirstOccurrence = false;
+ if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
+ + " now " + mHistoryBuffer.dataPosition()
+ + " size is now " + mHistoryBuffer.dataSize());
+ }
+
+ @GuardedBy("this")
+ void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
+ if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
+ final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
+ final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
+ if (diffUptimeMs < (diffElapsedMs - 20)) {
+ final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
+ mHistoryAddTmp.setTo(mHistoryLastWritten);
+ mHistoryAddTmp.wakelockTag = null;
+ mHistoryAddTmp.wakeReasonTag = null;
+ mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
+ mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
+ addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
+ }
+ }
+ mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
+ mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+ mTrackRunningHistoryUptimeMs = uptimeMs;
+ addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
+ }
+
+ @GuardedBy("this")
+ void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+ addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
+ }
+
+ @GuardedBy("this")
+ public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
String name, int uid) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
+ mHistoryCur.eventCode = code;
+ mHistoryCur.eventTag = mHistoryCur.localEventTag;
+ mHistoryCur.eventTag.string = name;
+ mHistoryCur.eventTag.uid = uid;
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ }
+
+ @GuardedBy("this")
+ void clearHistoryLocked() {
+ if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
+ mHistoryBaseTimeMs = 0;
+ mLastHistoryElapsedRealtimeMs = 0;
+ mTrackRunningHistoryElapsedRealtimeMs = 0;
+ mTrackRunningHistoryUptimeMs = 0;
+
+ mHistoryBuffer.setDataSize(0);
+ mHistoryBuffer.setDataPosition(0);
+ mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
+ mHistoryLastLastWritten.clear();
+ mHistoryLastWritten.clear();
+ mHistoryTagPool.clear();
+ mNextHistoryTagIdx = 0;
+ mNumHistoryTagChars = 0;
+ mHistoryBufferLastPos = -1;
+ mActiveHistoryStates = 0xffffffff;
+ mActiveHistoryStates2 = 0xffffffff;
}
@GuardedBy("this")
@@ -4221,13 +4663,13 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(code, name, uid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
@GuardedBy("this")
public void noteCurrentTimeChangedLocked(long currentTimeMs,
long elapsedRealtimeMs, long uptimeMs) {
- mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
+ recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
}
@GuardedBy("this")
@@ -4244,7 +4686,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mRecordAllHistory) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
}
@GuardedBy("this")
@@ -4302,7 +4744,8 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mRecordAllHistory) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
+ name, uid);
}
@GuardedBy("this")
@@ -4318,7 +4761,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
}
@GuardedBy("this")
@@ -4334,7 +4777,8 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
+ name, uid);
}
@GuardedBy("this")
@@ -4350,7 +4794,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
}
@GuardedBy("this")
@@ -4368,7 +4812,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4416,7 +4860,7 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i = 0; i < workSource.size(); ++i) {
uid = mapUid(workSource.getUid(i));
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
@@ -4425,7 +4869,7 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i = 0; i < workChains.size(); ++i) {
uid = mapUid(workChains.get(i).getAttributionUid());
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4433,7 +4877,7 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4508,7 +4952,7 @@ public class BatteryStatsImpl extends BatteryStats {
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- mHistory.recordEvent(mSecRealtime, mSecUptime,
+ addHistoryEventLocked(mSecRealtime, mSecUptime,
HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
}
}
@@ -4523,8 +4967,8 @@ public class BatteryStatsImpl extends BatteryStats {
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
- ent.getKey(), uids.keyAt(j));
+ addHistoryEventLocked(mSecRealtime, mSecUptime,
+ HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
}
}
}
@@ -4567,19 +5011,30 @@ public class BatteryStatsImpl extends BatteryStats {
if (mRecordAllHistory) {
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
mappedUid, 0)) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
}
}
if (mWakeLockNesting == 0) {
+ mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
+ + Integer.toHexString(mHistoryCur.states));
+ mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+ mHistoryCur.wakelockTag.string = historyName;
+ mHistoryCur.wakelockTag.uid = mappedUid;
mWakeLockImportant = !unimportantForLogging;
- mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
- mappedUid);
- } else if (!mWakeLockImportant && !unimportantForLogging) {
- if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
- mappedUid)) {
- mWakeLockImportant = true;
- }
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ } else if (!mWakeLockImportant && !unimportantForLogging
+ && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
+ if (mHistoryLastWritten.wakelockTag != null) {
+ // We'll try to update the last tag.
+ mHistoryLastWritten.wakelockTag = null;
+ mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+ mHistoryCur.wakelockTag.string = historyName;
+ mHistoryCur.wakelockTag.uid = mappedUid;
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ }
+ mWakeLockImportant = true;
}
mWakeLockNesting++;
}
@@ -4632,13 +5087,15 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
mappedUid, 0)) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
}
}
if (mWakeLockNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WAKE_LOCK_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
if (mappedUid >= 0) {
@@ -4829,7 +5286,7 @@ public class BatteryStatsImpl extends BatteryStats {
mappedUid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
historyName, mappedUid);
if (mappedUid != uid) {
// Prevent the isolated uid mapping from being removed while the wakelock is
@@ -4882,7 +5339,7 @@ public class BatteryStatsImpl extends BatteryStats {
mappedUid, 0)) {
return;
}
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
historyName, mappedUid);
if (mappedUid != uid) {
// Decrement the ref count for the isolated uid and delete the mapping if uneeded.
@@ -4904,10 +5361,15 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
+ if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
+ + Integer.toHexString(mHistoryCur.states));
aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
- mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
+ mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+ mHistoryCur.wakeReasonTag.string = reason;
+ mHistoryCur.wakeReasonTag.uid = 0;
mLastWakeupReason = reason;
mLastWakeupUptimeMs = uptimeMs;
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
@GuardedBy("this")
@@ -4918,11 +5380,22 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
- int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
- int statSoftIrqTimeMs, int statIdleTimeMs) {
- mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
- statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
- statSoftIrqTimeMs, statIdleTimeMs);
+ int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
+ int statSoftIrqTimeMs, int statIdleTimeMs) {
+ if (DEBUG) {
+ Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
+ + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
+ + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
+ + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
+ }
+ mCurStepCpuUserTimeMs += totalUTimeMs;
+ mCurStepCpuSystemTimeMs += totalSTimeMs;
+ mCurStepStatUserTimeMs += statUserTimeMs;
+ mCurStepStatSystemTimeMs += statSystemTimeMs;
+ mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
+ mCurStepStatIrqTimeMs += statIrqTimeMs;
+ mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
+ mCurStepStatIdleTimeMs += statIdleTimeMs;
}
public void noteProcessDiedLocked(int uid, int pid) {
@@ -4952,8 +5425,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mSensorNesting == 0) {
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_SENSOR_ON_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mSensorNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -4970,8 +5445,10 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
mSensorNesting--;
if (mSensorNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_SENSOR_ON_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteStopSensor(sensor, elapsedRealtimeMs);
@@ -5021,8 +5498,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
final int mappedUid = mapUid(uid);
if (mGpsNesting == 0) {
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_GPS_ON_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mGpsNesting++;
@@ -5047,8 +5526,10 @@ public class BatteryStatsImpl extends BatteryStats {
final int mappedUid = mapUid(uid);
mGpsNesting--;
if (mGpsNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_GPS_ON_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
mGpsSignalQualityBin = -1;
}
@@ -5081,9 +5562,12 @@ public class BatteryStatsImpl extends BatteryStats {
if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
}
- mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
+ mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
+ | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mGpsSignalQualityBin = signalLevel;
}
+ return;
}
@GuardedBy("this")
@@ -5256,33 +5740,41 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
- int startStates = 0;
- int stopStates = 0;
+ boolean updateHistory = false;
if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
- startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
+ mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
+ updateHistory = true;
} else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
- stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
+ mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
+ updateHistory = true;
}
if (Display.isOnState(state)) {
- startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
+ mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
+ + Integer.toHexString(mHistoryCur.states));
mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin]
.startRunningLocked(elapsedRealtimeMs);
}
+ updateHistory = true;
} else if (Display.isOnState(oldState)) {
- stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
+ mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
+ + Integer.toHexString(mHistoryCur.states));
mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin]
.stopRunningLocked(elapsedRealtimeMs);
}
+ updateHistory = true;
}
- if (startStates != 0 || stopStates != 0) {
- mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
- stopStates);
+ if (updateHistory) {
+ if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
+ + Display.stateToString(state));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
// Per screen state Cpu stats needed. Prepare to schedule an external sync.
@@ -5396,7 +5888,13 @@ public class BatteryStatsImpl extends BatteryStats {
long uptimeMs) {
if (mScreenBrightnessBin != overallBin) {
if (overallBin >= 0) {
- mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
+ mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
+ | (overallBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
+ if (DEBUG_HISTORY) {
+ Slog.v(TAG, "Screen brightness " + overallBin + " to: "
+ + Integer.toHexString(mHistoryCur.states));
+ }
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
if (mScreenState == Display.STATE_ON) {
if (mScreenBrightnessBin >= 0) {
@@ -5424,8 +5922,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWakeUpLocked(String reason, int reasonUid,
long elapsedRealtimeMs, long uptimeMs) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
- reasonUid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
+ reason, reasonUid);
}
@GuardedBy("this")
@@ -5444,7 +5942,7 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteConnectivityChangedLocked(int type, String extra,
long elapsedRealtimeMs, long uptimeMs) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
extra, type);
mNumConnectivityChange++;
}
@@ -5453,7 +5951,7 @@ public class BatteryStatsImpl extends BatteryStats {
private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
- mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
+ addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
}
@@ -5479,8 +5977,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
} else {
realElapsedRealtimeMs = timestampNs / (1000*1000);
long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
@@ -5492,9 +5989,11 @@ public class BatteryStatsImpl extends BatteryStats {
mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
- realElapsedRealtimeMs);
}
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
}
+ if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mMobileRadioPowerState = powerState;
// Inform current RatBatteryStats that the modem active state might have changed.
@@ -5544,14 +6043,17 @@ public class BatteryStatsImpl extends BatteryStats {
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
mPowerSaveModeEnabled = enabled;
if (enabled) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_POWER_SAVE_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
+ + Integer.toHexString(mHistoryCur.states2));
mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_POWER_SAVE_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
+ + Integer.toHexString(mHistoryCur.states2));
mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
}
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
enabled
? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
@@ -5575,7 +6077,7 @@ public class BatteryStatsImpl extends BatteryStats {
nowLightIdling = true;
}
if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
activeReason, activeUid);
}
if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
@@ -5605,7 +6107,11 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
if (mDeviceIdleMode != mode) {
- mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
+ mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
+ | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
mLastIdleTimeStartMs = elapsedRealtimeMs;
if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
@@ -5633,7 +6139,7 @@ public class BatteryStatsImpl extends BatteryStats {
public void notePackageInstalledLocked(String pkgName, long versionCode,
long elapsedRealtimeMs, long uptimeMs) {
// XXX need to figure out what to do with long version codes.
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
pkgName, (int)versionCode);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
@@ -5645,8 +6151,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePackageUninstalledLocked(String pkgName,
long elapsedRealtimeMs, long uptimeMs) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
- pkgName, 0);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
pc.mUpdate = true;
@@ -5675,8 +6181,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mPhoneOn) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mPhoneOn = true;
mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -5685,8 +6193,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mPhoneOn) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mPhoneOn = false;
mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
@@ -5724,12 +6234,11 @@ public class BatteryStatsImpl extends BatteryStats {
if (mUsbDataState != newState) {
mUsbDataState = newState;
if (connected) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_USB_DATA_LINK_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
} else {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_USB_DATA_LINK_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
}
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -5750,10 +6259,6 @@ public class BatteryStatsImpl extends BatteryStats {
long elapsedRealtimeMs, long uptimeMs) {
boolean scanning = false;
boolean newHistory = false;
- int addStateFlag = 0;
- int removeStateFlag = 0;
- int newState = -1;
- int newSignalStrength = -1;
mPhoneServiceStateRaw = state;
mPhoneSimStateRaw = simState;
@@ -5782,8 +6287,10 @@ public class BatteryStatsImpl extends BatteryStats {
scanning = true;
strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (!mPhoneSignalScanningTimer.isRunningLocked()) {
- addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
+ mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
newHistory = true;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
+ + Integer.toHexString(mHistoryCur.states));
mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
simState, strengthBin);
@@ -5793,7 +6300,9 @@ public class BatteryStatsImpl extends BatteryStats {
if (!scanning) {
// If we are no longer scanning, then stop the scanning timer.
if (mPhoneSignalScanningTimer.isRunningLocked()) {
- removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
+ mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
+ + Integer.toHexString(mHistoryCur.states));
newHistory = true;
mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
@@ -5802,7 +6311,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (mPhoneServiceState != state) {
- newState = state;
+ mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
+ | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
+ + Integer.toHexString(mHistoryCur.states));
newHistory = true;
mPhoneServiceState = state;
}
@@ -5816,7 +6328,11 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- newSignalStrength = strengthBin;
+ mHistoryCur.states =
+ (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
+ | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
+ + Integer.toHexString(mHistoryCur.states));
newHistory = true;
FrameworkStatsLog.write(
FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
@@ -5827,8 +6343,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (newHistory) {
- mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
- addStateFlag, removeStateFlag, newState, newSignalStrength);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -5952,7 +6467,11 @@ public class BatteryStatsImpl extends BatteryStats {
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != bin) {
- mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
+ mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
+ | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
if (mPhoneDataConnectionType >= 0) {
mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
elapsedRealtimeMs);
@@ -6025,8 +6544,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mWifiOn) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_WIFI_ON_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiOn = true;
mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
@@ -6036,8 +6557,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mWifiOn) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_WIFI_ON_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
@@ -6048,8 +6571,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mAudioOnNesting == 0) {
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_AUDIO_ON_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mAudioOnNesting++;
@@ -6064,8 +6589,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mAudioOnNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_AUDIO_ON_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6076,8 +6603,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mVideoOnNesting == 0) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_VIDEO_ON_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mVideoOnNesting++;
@@ -6092,8 +6621,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mVideoOnNesting == 0) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_VIDEO_ON_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6104,8 +6635,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting > 0) {
mAudioOnNesting = 0;
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_AUDIO_ON_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6118,8 +6651,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting > 0) {
mVideoOnNesting = 0;
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_VIDEO_ON_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6171,8 +6706,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mFlashlightOnNesting++ == 0) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_FLASHLIGHT_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6186,8 +6723,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mFlashlightOnNesting == 0) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_FLASHLIGHT_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6198,8 +6737,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mCameraOnNesting++ == 0) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_CAMERA_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6213,8 +6754,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mCameraOnNesting == 0) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_CAMERA_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6225,8 +6768,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting > 0) {
mCameraOnNesting = 0;
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_CAMERA_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6239,8 +6784,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting > 0) {
mFlashlightOnNesting = 0;
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_FLASHLIGHT_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6257,8 +6804,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (mBluetoothScanNesting == 0) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
}
mBluetoothScanNesting++;
@@ -6299,8 +6848,10 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
mBluetoothScanNesting--;
if (mBluetoothScanNesting == 0) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6335,8 +6886,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mBluetoothScanNesting > 0) {
mBluetoothScanNesting = 0;
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6376,7 +6929,7 @@ public class BatteryStatsImpl extends BatteryStats {
private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
- mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
+ addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
}
@@ -6392,14 +6945,15 @@ public class BatteryStatsImpl extends BatteryStats {
if (uid > 0) {
noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
}
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
}
+ if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiRadioPowerState = powerState;
}
}
@@ -6407,8 +6961,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (!mGlobalWifiRunning) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_WIFI_RUNNING_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mGlobalWifiRunning = true;
mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
int N = ws.size();
@@ -6476,8 +7032,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
- mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_WIFI_RUNNING_FLAG);
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mGlobalWifiRunning = false;
mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
int N = ws.size();
@@ -6525,7 +7083,12 @@ public class BatteryStatsImpl extends BatteryStats {
}
mWifiSupplState = supplState;
mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
- mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
+ mHistoryCur.states2 =
+ (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
+ | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -6554,8 +7117,12 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
- strengthBin);
+ mHistoryCur.states2 =
+ (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
+ | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
} else {
stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
}
@@ -6568,8 +7135,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiFullLockNesting == 0) {
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mWifiFullLockNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6580,8 +7149,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiFullLockNesting--;
if (mWifiFullLockNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
@@ -6597,8 +7168,10 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiScanNesting == 0) {
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_SCAN_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mWifiScanNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6614,8 +7187,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiScanNesting--;
if (mWifiScanNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_SCAN_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteWifiScanStoppedLocked(elapsedRealtimeMs);
@@ -6640,10 +7215,14 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mWifiMulticastNesting == 0) {
- mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
+ mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+
// Start Wifi Multicast overall timer
if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
+ if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
}
}
@@ -6657,12 +7236,14 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
mWifiMulticastNesting--;
if (mWifiMulticastNesting == 0) {
- mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
+ mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
// Stop Wifi Multicast overall timer
if (mWifiMulticastWakelockTimer.isRunningLocked()) {
- if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
+ if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
@@ -7414,9 +7995,8 @@ public class BatteryStatsImpl extends BatteryStats {
// If the start clock time has changed by more than a year, then presumably
// the previous time was completely bogus. So we are going to figure out a
// new time based on how much time has elapsed since we started counting.
- mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
- currentTimeMs
- );
+ recordCurrentTimeChangeLocked(currentTimeMs, mClock.elapsedRealtime(),
+ mClock.uptimeMillis());
return currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
}
return mStartClockTimeMs;
@@ -10648,19 +11228,18 @@ public class BatteryStatsImpl extends BatteryStats {
UserInfoProvider userInfoProvider) {
init(clock);
- mHandler = new MyHandler(handler.getLooper());
- mConstants = new Constants(mHandler);
-
if (systemDir == null) {
mStatsFile = null;
- mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
+ mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
} else {
mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
- mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES,
- mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
+ mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, systemDir,
+ this::getMaxHistoryFiles);
}
mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
+ mHandler = new MyHandler(handler.getLooper());
+ mConstants = new Constants(mHandler);
mStartCount++;
initTimersAndCounters();
mOnBattery = mOnBatteryInternal = false;
@@ -10669,6 +11248,7 @@ public class BatteryStatsImpl extends BatteryStats {
initTimes(uptimeUs, realtimeUs);
mStartPlatformVersion = mEndPlatformVersion = Build.ID;
initDischarge(realtimeUs);
+ clearHistoryLocked();
updateDailyDeadlineLocked();
mPlatformIdleStateCallback = cb;
mMeasuredEnergyRetriever = energyStatsCb;
@@ -10679,6 +11259,12 @@ public class BatteryStatsImpl extends BatteryStats {
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
}
+ private int getMaxHistoryFiles() {
+ synchronized (this) {
+ return mConstants.MAX_HISTORY_FILES;
+ }
+ }
+
@VisibleForTesting
protected void initTimersAndCounters() {
mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
@@ -10760,7 +11346,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeUnplugLevel = 0;
mDischargePlugLevel = -1;
mDischargeCurrentLevel = 0;
- mBatteryLevel = 0;
+ mCurrentBatteryLevel = 0;
}
public void setPowerProfileLocked(PowerProfile profile) {
@@ -11147,7 +11733,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
public int getHistoryUsedSize() {
- return mHistory.getHistoryUsedSize();
+ return mBatteryStatsHistory.getHistoryUsedSize();
}
@Override
@@ -11161,27 +11747,43 @@ public class BatteryStatsImpl extends BatteryStats {
*/
@VisibleForTesting
public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
- return mHistory.iterate();
+ return new BatteryStatsHistoryIterator(mBatteryStatsHistory);
}
@Override
public int getHistoryStringPoolSize() {
- return mHistory.getHistoryStringPoolSize();
+ return mHistoryTagPool.size();
}
@Override
public int getHistoryStringPoolBytes() {
- return mHistory.getHistoryStringPoolBytes();
+ return mNumHistoryTagChars;
}
@Override
public String getHistoryTagPoolString(int index) {
- return mHistory.getHistoryTagPoolString(index);
+ ensureHistoryTagArray();
+ HistoryTag historyTag = mHistoryTags.get(index);
+ return historyTag != null ? historyTag.string : null;
}
@Override
public int getHistoryTagPoolUid(int index) {
- return mHistory.getHistoryTagPoolUid(index);
+ ensureHistoryTagArray();
+ HistoryTag historyTag = mHistoryTags.get(index);
+ return historyTag != null ? historyTag.uid : Process.INVALID_UID;
+ }
+
+ private void ensureHistoryTagArray() {
+ if (mHistoryTags != null) {
+ return;
+ }
+
+ mHistoryTags = new SparseArray<>(mHistoryTagPool.size());
+ for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
+ mHistoryTags.put(entry.getValue() & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG,
+ entry.getKey());
+ }
}
@Override
@@ -11191,11 +11793,15 @@ public class BatteryStatsImpl extends BatteryStats {
@Override
public void finishIteratingHistoryLocked() {
- mBatteryStatsHistoryIterator.close();
mBatteryStatsHistoryIterator = null;
}
@Override
+ public long getHistoryBaseTime() {
+ return mHistoryBaseTimeMs;
+ }
+
+ @Override
public int getStartCount() {
return mStartCount;
}
@@ -11248,23 +11854,24 @@ public class BatteryStatsImpl extends BatteryStats {
long realtimeUs = mSecRealtime * 1000;
resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
pullPendingStateUpdatesLocked();
- mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
- mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
+ addHistoryRecordLocked(mSecRealtime, mSecUptime);
+ mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
+ = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
- if (!mBatteryPluggedIn) {
+ if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
if (Display.isOnState(mScreenState)) {
- mDischargeScreenOnUnplugLevel = mBatteryLevel;
+ mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
mDischargeScreenDozeUnplugLevel = 0;
mDischargeScreenOffUnplugLevel = 0;
} else if (Display.isDozeState(mScreenState)) {
mDischargeScreenOnUnplugLevel = 0;
- mDischargeScreenDozeUnplugLevel = mBatteryLevel;
+ mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
mDischargeScreenOffUnplugLevel = 0;
} else {
mDischargeScreenOnUnplugLevel = 0;
mDischargeScreenDozeUnplugLevel = 0;
- mDischargeScreenOffUnplugLevel = mBatteryLevel;
+ mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
}
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
@@ -11408,12 +12015,27 @@ public class BatteryStatsImpl extends BatteryStats {
resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
+ mLastHistoryStepDetails = null;
+ mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0;
+ mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0;
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
+
mNumAllUidCpuTimeReads = 0;
mNumUidsRemoved = 0;
initDischarge(elapsedRealtimeUs);
- mHistory.reset();
+ clearHistoryLocked();
+ if (mBatteryStatsHistory != null) {
+ mBatteryStatsHistory.resetAllFiles();
+ }
// Flush external data, gathering snapshots, but don't process it since it is pre-reset data
mIgnoreNextExternalStats = true;
@@ -11436,7 +12058,7 @@ public class BatteryStatsImpl extends BatteryStats {
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
uids.keyAt(j));
}
}
@@ -11861,8 +12483,9 @@ public class BatteryStatsImpl extends BatteryStats {
(long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
monitoredRailChargeConsumedMaMs);
- mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
- (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
+ mHistoryCur.wifiRailChargeMah +=
+ (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetWifiTotalEnergyUsed();
if (uidEstimatedConsumptionMah != null) {
@@ -11975,8 +12598,9 @@ public class BatteryStatsImpl extends BatteryStats {
(long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
monitoredRailChargeConsumedMaMs);
- mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
- (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
+ mHistoryCur.modemRailChargeMah +=
+ (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetCellularTotalEnergyUsed();
}
@@ -12244,8 +12868,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
- mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
- HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
+ mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -13678,7 +14302,11 @@ public class BatteryStatsImpl extends BatteryStats {
mHandler.removeCallbacks(mDeferSetCharging);
if (mCharging != charging) {
mCharging = charging;
- mHistory.setChargingState(charging);
+ if (charging) {
+ mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
+ } else {
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
+ }
mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
return true;
}
@@ -13692,15 +14320,6 @@ public class BatteryStatsImpl extends BatteryStats {
mSystemReady = true;
}
- /**
- * Force recording of all history events regardless of the "charging" state.
- */
- @VisibleForTesting
- public void forceRecordAllHistory() {
- mHistory.forceRecordAllHistory();
- mRecordAllHistory = true;
- }
-
@GuardedBy("this")
protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
@@ -13784,12 +14403,15 @@ public class BatteryStatsImpl extends BatteryStats {
mInitStepMode = mCurStepMode;
mModStepMode = 0;
pullPendingStateUpdatesLocked();
+ mHistoryCur.batteryLevel = (byte)level;
+ mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
+ + Integer.toHexString(mHistoryCur.states));
if (reset) {
- mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
- initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
+ mRecordingHistory = true;
+ startRecordingHistory(mSecRealtime, mSecUptime, reset);
}
- mBatteryPluggedIn = false;
- mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
+ addHistoryRecordLocked(mSecRealtime, mSecUptime);
mDischargeCurrentLevel = mDischargeUnplugLevel = level;
if (Display.isOnState(screenState)) {
mDischargeScreenOnUnplugLevel = level;
@@ -13811,8 +14433,11 @@ public class BatteryStatsImpl extends BatteryStats {
} else {
mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
- mBatteryPluggedIn = true;
- mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
+ mHistoryCur.batteryLevel = (byte)level;
+ mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(mSecRealtime, mSecUptime);
mDischargeCurrentLevel = mDischargePlugLevel = level;
if (level < mDischargeUnplugLevel) {
mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
@@ -13827,12 +14452,45 @@ public class BatteryStatsImpl extends BatteryStats {
mModStepMode = 0;
}
if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
- if (mStatsFile != null && !mHistory.isReadOnly()) {
+ if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
writeAsyncLocked();
}
}
}
+ @GuardedBy("this")
+ private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
+ boolean reset) {
+ mRecordingHistory = true;
+ mHistoryCur.currentTime = mClock.currentTimeMillis();
+ addHistoryBufferLocked(elapsedRealtimeMs,
+ reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
+ mHistoryCur);
+ mHistoryCur.currentTime = 0;
+ if (reset) {
+ initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
+ }
+ }
+
+ @GuardedBy("this")
+ private void recordCurrentTimeChangeLocked(final long currentTimeMs,
+ final long elapsedRealtimeMs, final long uptimeMs) {
+ if (mRecordingHistory) {
+ mHistoryCur.currentTime = currentTimeMs;
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
+ mHistoryCur.currentTime = 0;
+ }
+ }
+
+ @GuardedBy("this")
+ private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
+ if (mRecordingHistory) {
+ mHistoryCur.currentTime = currentTimeMs;
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
+ mHistoryCur.currentTime = 0;
+ }
+ }
+
private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
if (mExternalSync != null) {
mExternalSync.scheduleSync(reason, updateFlags);
@@ -13850,7 +14508,8 @@ public class BatteryStatsImpl extends BatteryStats {
// Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
temp = Math.max(0, temp);
- reportChangesToStatsLog(status, plugType, level);
+ reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
+ status, plugType, level);
final boolean onBattery = isOnBattery(plugType, status);
if (!mHaveBatteryLevel) {
@@ -13860,47 +14519,52 @@ public class BatteryStatsImpl extends BatteryStats {
// plugged in, then twiddle our state to correctly reflect that
// since we won't be going through the full setOnBattery().
if (onBattery == mOnBattery) {
- mHistory.setPluggedInState(!onBattery);
+ if (onBattery) {
+ mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ } else {
+ mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ }
}
- mBatteryStatus = status;
- mBatteryLevel = level;
- mBatteryChargeUah = chargeUah;
-
// Always start out assuming charging, that will be updated later.
- mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
-
+ mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
+ mHistoryCur.batteryStatus = (byte)status;
+ mHistoryCur.batteryLevel = (byte)level;
+ mHistoryCur.batteryChargeUah = chargeUah;
mMaxChargeStepLevel = mMinDischargeStepLevel =
mLastChargeStepLevel = mLastDischargeStepLevel = level;
- } else if (mBatteryLevel != level || mOnBattery != onBattery) {
+ } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
}
- int oldStatus = mBatteryStatus;
+ int oldStatus = mHistoryCur.batteryStatus;
if (onBattery) {
mDischargeCurrentLevel = level;
- if (!mHistory.isRecordingHistory()) {
- mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
+ if (!mRecordingHistory) {
+ mRecordingHistory = true;
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
} else if (level < 96 &&
status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
- if (!mHistory.isRecordingHistory()) {
- mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
+ if (!mRecordingHistory) {
+ mRecordingHistory = true;
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
}
+ mBatteryVoltageMv = voltageMv;
+ mCurrentBatteryLevel = level;
if (mDischargePlugLevel < 0) {
mDischargePlugLevel = level;
}
if (onBattery != mOnBattery) {
- mBatteryLevel = level;
- mBatteryStatus = status;
- mBatteryHealth = health;
- mBatteryPlugType = plugType;
- mBatteryTemperature = temp;
- mBatteryVoltageMv = voltageMv;
- mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
- if (chargeUah < mBatteryChargeUah) {
+ mHistoryCur.batteryLevel = (byte)level;
+ mHistoryCur.batteryStatus = (byte)status;
+ mHistoryCur.batteryHealth = (byte)health;
+ mHistoryCur.batteryPlugType = (byte)plugType;
+ mHistoryCur.batteryTemperature = (short)temp;
+ mHistoryCur.batteryVoltage = (char) voltageMv;
+ if (chargeUah < mHistoryCur.batteryChargeUah) {
// Only record discharges
- final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
+ final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -13912,12 +14576,12 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
- mBatteryChargeUah = chargeUah;
+ mHistoryCur.batteryChargeUah = chargeUah;
setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
} else {
boolean changed = false;
- if (mBatteryLevel != level) {
- mBatteryLevel = level;
+ if (mHistoryCur.batteryLevel != level) {
+ mHistoryCur.batteryLevel = (byte)level;
changed = true;
// TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
@@ -13925,33 +14589,33 @@ public class BatteryStatsImpl extends BatteryStats {
mExternalSync.scheduleSyncDueToBatteryLevelChange(
mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
}
- if (mBatteryStatus != status) {
- mBatteryStatus = status;
+ if (mHistoryCur.batteryStatus != status) {
+ mHistoryCur.batteryStatus = (byte)status;
changed = true;
}
- if (mBatteryHealth != health) {
- mBatteryHealth = health;
+ if (mHistoryCur.batteryHealth != health) {
+ mHistoryCur.batteryHealth = (byte)health;
changed = true;
}
- if (mBatteryPlugType != plugType) {
- mBatteryPlugType = plugType;
+ if (mHistoryCur.batteryPlugType != plugType) {
+ mHistoryCur.batteryPlugType = (byte)plugType;
changed = true;
}
- if (temp >= (mBatteryTemperature + 10)
- || temp <= (mBatteryTemperature - 10)) {
- mBatteryTemperature = temp;
+ if (temp >= (mHistoryCur.batteryTemperature+10)
+ || temp <= (mHistoryCur.batteryTemperature-10)) {
+ mHistoryCur.batteryTemperature = (short)temp;
changed = true;
}
- if (voltageMv > (mBatteryVoltageMv + 20)
- || voltageMv < (mBatteryVoltageMv - 20)) {
- mBatteryVoltageMv = voltageMv;
+ if (voltageMv > (mHistoryCur.batteryVoltage + 20)
+ || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
+ mHistoryCur.batteryVoltage = (char) voltageMv;
changed = true;
}
- if (chargeUah >= (mBatteryChargeUah + 10)
- || chargeUah <= (mBatteryChargeUah - 10)) {
- if (chargeUah < mBatteryChargeUah) {
+ if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
+ || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
+ if (chargeUah < mHistoryCur.batteryChargeUah) {
// Only record discharges
- final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
+ final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -13963,10 +14627,9 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
- mBatteryChargeUah = chargeUah;
+ mHistoryCur.batteryChargeUah = chargeUah;
changed = true;
}
-
long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
| (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
| (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
@@ -14024,10 +14687,7 @@ public class BatteryStatsImpl extends BatteryStats {
mLastChargeStepLevel = level;
}
if (changed) {
- mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
- mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
- mBatteryChargeUah);
- mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
if (!onBattery &&
@@ -14036,7 +14696,7 @@ public class BatteryStatsImpl extends BatteryStats {
// We don't record history while we are plugged in and fully charged
// (or when battery is not present). The next time we are
// unplugged, history will be cleared.
- mHistory.setHistoryRecordingEnabled(DEBUG);
+ mRecordingHistory = DEBUG;
}
mLastLearnedBatteryCapacityUah = chargeFullUah;
@@ -14055,18 +14715,17 @@ public class BatteryStatsImpl extends BatteryStats {
}
// Inform StatsLog of setBatteryState changes.
- private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
- if (!mHaveBatteryLevel) {
- return;
- }
+ // If this is the first reporting, pass in recentPast == null.
+ private void reportChangesToStatsLog(HistoryItem recentPast,
+ final int status, final int plugType, final int level) {
- if (mBatteryStatus != status) {
+ if (recentPast == null || recentPast.batteryStatus != status) {
FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
}
- if (mBatteryPlugType != plugType) {
+ if (recentPast == null || recentPast.batteryPlugType != plugType) {
FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
}
- if (mBatteryLevel != level) {
+ if (recentPast == null || recentPast.batteryLevel != level) {
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
}
}
@@ -14136,7 +14795,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (msPerLevel <= 0) {
return -1;
}
- return (msPerLevel * mBatteryLevel) * 1000;
+ return (msPerLevel * mCurrentBatteryLevel) * 1000;
}
@Override
@@ -14166,7 +14825,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (msPerLevel <= 0) {
return -1;
}
- return (msPerLevel * (100 - mBatteryLevel)) * 1000;
+ return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
}
/*@hide */
@@ -14597,8 +15256,7 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void shutdownLocked() {
- mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
- mClock.currentTimeMillis());
+ recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime());
writeSyncLocked();
mShuttingDown = true;
}
@@ -14806,6 +15464,7 @@ public class BatteryStatsImpl extends BatteryStats {
PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
+
MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
ActivityManager.isLowRamDeviceStatic() ?
DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
@@ -14816,20 +15475,9 @@ public class BatteryStatsImpl extends BatteryStats {
: DEFAULT_MAX_HISTORY_BUFFER_KB)
* 1024;
updateBatteryChargedDelayMsLocked();
-
- onChange();
}
}
- /**
- * Propagates changes in constant values.
- */
- @VisibleForTesting
- public void onChange() {
- mHistory.setMaxHistoryFiles(MAX_HISTORY_FILES);
- mHistory.setMaxHistoryBufferSize(MAX_HISTORY_BUFFER);
- }
-
private void updateBatteryChargedDelayMsLocked() {
// a negative value indicates that we should ignore this override
final int delay = Settings.Global.getInt(mResolver,
@@ -15050,11 +15698,27 @@ public class BatteryStatsImpl extends BatteryStats {
}
private void writeHistoryLocked() {
+ if (mBatteryStatsHistory.getActiveFile() == null) {
+ Slog.w(TAG, "writeHistoryLocked: no history file associated with this instance");
+ return;
+ }
+
if (mShuttingDown) {
return;
}
- mHistory.writeHistory();
+ Parcel p = Parcel.obtain();
+ try {
+ final long start = SystemClock.uptimeMillis();
+ writeHistoryBuffer(p, true);
+ if (DEBUG) {
+ Slog.d(TAG, "writeHistoryBuffer duration ms:"
+ + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
+ }
+ writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile());
+ } finally {
+ p.recycle();
+ }
}
private final ReentrantLock mWriteLock = new ReentrantLock();
@@ -15093,6 +15757,13 @@ public class BatteryStatsImpl extends BatteryStats {
return;
}
+ final AtomicFile activeHistoryFile = mBatteryStatsHistory.getActiveFile();
+ if (activeHistoryFile == null) {
+ Slog.w(TAG,
+ "readLocked: no history file associated with this instance");
+ return;
+ }
+
mUidStats.clear();
Parcel stats = Parcel.obtain();
@@ -15105,7 +15776,7 @@ public class BatteryStatsImpl extends BatteryStats {
readSummaryFromParcel(stats);
if (DEBUG) {
Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
- + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
+ + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
- start));
}
}
@@ -15117,19 +15788,126 @@ public class BatteryStatsImpl extends BatteryStats {
stats.recycle();
}
- if (!mHistory.readSummary()) {
- resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
- RESET_REASON_CORRUPT_FILE);
+ Parcel history = Parcel.obtain();
+ try {
+ final long start = SystemClock.uptimeMillis();
+ if (activeHistoryFile.exists()) {
+ byte[] raw = activeHistoryFile.readFully();
+ if (raw.length > 0) {
+ history.unmarshall(raw, 0, raw.length);
+ history.setDataPosition(0);
+ readHistoryBuffer(history);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "readLocked history file::"
+ + activeHistoryFile.getBaseFile().getPath()
+ + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
+ - start));
+ }
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error reading battery history", e);
+ clearHistoryLocked();
+ mBatteryStatsHistory.resetAllFiles();
+ } finally {
+ history.recycle();
}
mEndPlatformVersion = Build.ID;
- mHistory.continueRecordingHistory();
+ if (mHistoryBuffer.dataPosition() > 0
+ || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
+ mRecordingHistory = true;
+ final long elapsedRealtimeMs = mClock.elapsedRealtime();
+ final long uptimeMs = mClock.uptimeMillis();
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
+ }
recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
}
@GuardedBy("this")
+ void readHistoryBuffer(Parcel in) throws ParcelFormatException {
+ final int version = in.readInt();
+ if (version != BatteryStatsHistory.VERSION) {
+ Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
+ + ", expected " + BatteryStatsHistory.VERSION + "; erasing old stats");
+ return;
+ }
+
+ final long historyBaseTime = in.readLong();
+
+ mHistoryBuffer.setDataSize(0);
+ mHistoryBuffer.setDataPosition(0);
+
+ int bufSize = in.readInt();
+ int curPos = in.dataPosition();
+ if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
+ throw new ParcelFormatException("File corrupt: history data buffer too large " +
+ bufSize);
+ } else if ((bufSize&~3) != bufSize) {
+ throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
+ bufSize);
+ } else {
+ if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
+ + " bytes at " + curPos);
+ mHistoryBuffer.appendFrom(in, curPos, bufSize);
+ in.setDataPosition(curPos + bufSize);
+ }
+
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** OLD mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ mHistoryBaseTimeMs = historyBaseTime;
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** NEW mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+
+ // We are just arbitrarily going to insert 1 minute from the sample of
+ // the last run until samples in this run.
+ if (mHistoryBaseTimeMs > 0) {
+ long oldnow = mClock.elapsedRealtime();
+ mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ }
+ }
+
+ void writeHistoryBuffer(Parcel out, boolean inclData) {
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** WRITING mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ sb.append(" mLastHistoryElapsedRealtimeMs: ");
+ TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ out.writeInt(BatteryStatsHistory.VERSION);
+ out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
+ if (!inclData) {
+ out.writeInt(0);
+ out.writeInt(0);
+ return;
+ }
+
+ out.writeInt(mHistoryBuffer.dataSize());
+ if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
+ + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
+ out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+ }
+
+ @GuardedBy("this")
public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
final int version = in.readInt();
@@ -15139,7 +15917,31 @@ public class BatteryStatsImpl extends BatteryStats {
return;
}
- mHistory.readSummaryFromParcel(in);
+ boolean inclHistory = in.readBoolean();
+ if (inclHistory) {
+ readHistoryBuffer(in);
+ mBatteryStatsHistory.readFromParcel(in);
+ }
+
+ mHistoryTagPool.clear();
+ mNextHistoryTagIdx = 0;
+ mNumHistoryTagChars = 0;
+
+ int numTags = in.readInt();
+ for (int i=0; i<numTags; i++) {
+ int idx = in.readInt();
+ String str = in.readString();
+ int uid = in.readInt();
+ HistoryTag tag = new HistoryTag();
+ tag.string = str;
+ tag.uid = uid;
+ tag.poolIdx = idx;
+ mHistoryTagPool.put(tag, idx);
+ if (idx >= mNextHistoryTagIdx) {
+ mNextHistoryTagIdx = idx+1;
+ }
+ mNumHistoryTagChars += tag.string.length() + 1;
+ }
mStartCount = in.readInt();
mUptimeUs = in.readLong();
@@ -15152,7 +15954,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeUnplugLevel = in.readInt();
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
- mBatteryLevel = in.readInt();
+ mCurrentBatteryLevel = in.readInt();
mEstimatedBatteryCapacityMah = in.readInt();
mLastLearnedBatteryCapacityUah = in.readInt();
mMinLearnedBatteryCapacityUah = in.readInt();
@@ -15655,7 +16457,19 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(VERSION);
- mHistory.writeSummaryToParcel(out, inclHistory);
+ out.writeBoolean(inclHistory);
+ if (inclHistory) {
+ writeHistoryBuffer(out, true);
+ mBatteryStatsHistory.writeToParcel(out);
+ }
+
+ out.writeInt(mHistoryTagPool.size());
+ for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
+ HistoryTag tag = ent.getKey();
+ out.writeInt(ent.getValue());
+ out.writeString(tag.string);
+ out.writeInt(tag.uid);
+ }
out.writeInt(mStartCount);
out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
@@ -15668,7 +16482,7 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(mDischargeUnplugLevel);
out.writeInt(mDischargePlugLevel);
out.writeInt(mDischargeCurrentLevel);
- out.writeInt(mBatteryLevel);
+ out.writeInt(mCurrentBatteryLevel);
out.writeInt(mEstimatedBatteryCapacityMah);
out.writeInt(mLastLearnedBatteryCapacityUah);
out.writeInt(mMinLearnedBatteryCapacityUah);
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index c36d950b6cf6..0cdd4d101459 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -22,6 +22,7 @@ import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
+import android.os.Parcel;
import android.os.Process;
import android.os.SystemClock;
import android.os.UidBatteryConsumer;
@@ -31,8 +32,10 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.PowerProfile;
+import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -217,7 +220,18 @@ public class BatteryUsageStatsProvider {
}
BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;
- batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.copyHistory());
+
+ // Make a copy of battery history to avoid concurrent modification.
+ Parcel historyBuffer = Parcel.obtain();
+ historyBuffer.appendFrom(batteryStatsImpl.mHistoryBuffer, 0,
+ batteryStatsImpl.mHistoryBuffer.dataSize());
+
+ final File systemDir =
+ batteryStatsImpl.mBatteryStatsHistory.getHistoryDirectory().getParentFile();
+ final BatteryStatsHistory batteryStatsHistory =
+ new BatteryStatsHistory(historyBuffer, systemDir, null);
+
+ batteryUsageStatsBuilder.setBatteryHistory(batteryStatsHistory);
}
BatteryUsageStats stats = batteryUsageStatsBuilder.build();
diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java
index 994f07959f3b..5a2409927ecc 100644
--- a/services/core/java/com/android/server/wm/AppWarnings.java
+++ b/services/core/java/com/android/server/wm/AppWarnings.java
@@ -17,8 +17,12 @@
package com.android.server.wm;
import android.annotation.UiThread;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Handler;
@@ -305,21 +309,21 @@ class AppWarnings {
private void hideDialogsForPackageUiThread(String name) {
// Hides the "unsupported display" dialog if necessary.
if (mUnsupportedDisplaySizeDialog != null && (name == null || name.equals(
- mUnsupportedDisplaySizeDialog.getPackageName()))) {
+ mUnsupportedDisplaySizeDialog.mPackageName))) {
mUnsupportedDisplaySizeDialog.dismiss();
mUnsupportedDisplaySizeDialog = null;
}
// Hides the "unsupported compile SDK" dialog if necessary.
if (mUnsupportedCompileSdkDialog != null && (name == null || name.equals(
- mUnsupportedCompileSdkDialog.getPackageName()))) {
+ mUnsupportedCompileSdkDialog.mPackageName))) {
mUnsupportedCompileSdkDialog.dismiss();
mUnsupportedCompileSdkDialog = null;
}
// Hides the "deprecated target sdk version" dialog if necessary.
if (mDeprecatedTargetSdkVersionDialog != null && (name == null || name.equals(
- mDeprecatedTargetSdkVersionDialog.getPackageName()))) {
+ mDeprecatedTargetSdkVersionDialog.mPackageName))) {
mDeprecatedTargetSdkVersionDialog.dismiss();
mDeprecatedTargetSdkVersionDialog = null;
}
@@ -431,6 +435,49 @@ class AppWarnings {
}
}
+ static class BaseDialog {
+ final AppWarnings mManager;
+ final String mPackageName;
+ AlertDialog mDialog;
+ private BroadcastReceiver mCloseReceiver;
+
+ BaseDialog(AppWarnings manager, String packageName) {
+ mManager = manager;
+ mPackageName = packageName;
+ }
+
+ @UiThread
+ void show() {
+ if (mDialog == null) return;
+ if (mCloseReceiver == null) {
+ mCloseReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ mManager.mUiHandler.hideDialogsForPackage(mPackageName);
+ }
+ }
+ };
+ mManager.mUiContext.registerReceiver(mCloseReceiver,
+ new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
+ Context.RECEIVER_EXPORTED);
+ }
+ Slog.w(TAG, "Showing " + getClass().getSimpleName() + " for package " + mPackageName);
+ mDialog.show();
+ }
+
+ @UiThread
+ void dismiss() {
+ if (mDialog == null) return;
+ if (mCloseReceiver != null) {
+ mManager.mUiContext.unregisterReceiver(mCloseReceiver);
+ mCloseReceiver = null;
+ }
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ }
+
/**
* Handles messages on the ActivityTaskManagerService thread.
*/
diff --git a/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java b/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java
index 37244bd5bd06..1a7a9b258400 100644
--- a/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java
+++ b/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java
@@ -16,31 +16,23 @@
package com.android.server.wm;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
-import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import com.android.internal.R;
import com.android.server.utils.AppInstallerUtil;
-public class DeprecatedTargetSdkVersionDialog {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "DeprecatedTargetSdkVersionDialog" : TAG_ATM;
-
- private final AlertDialog mDialog;
- private final String mPackageName;
+class DeprecatedTargetSdkVersionDialog extends AppWarnings.BaseDialog {
- public DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context,
+ DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context,
ApplicationInfo appInfo) {
- mPackageName = appInfo.packageName;
+ super(manager, appInfo.packageName);
final PackageManager pm = context.getPackageManager();
final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -75,17 +67,4 @@ public class DeprecatedTargetSdkVersionDialog {
// DO NOT MODIFY. Used by CTS to verify the dialog is displayed.
window.getAttributes().setTitle("DeprecatedTargetSdkVersionDialog");
}
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public void show() {
- Log.w(TAG, "Showing SDK deprecation warning for package " + mPackageName);
- mDialog.show();
- }
-
- public void dismiss() {
- mDialog.dismiss();
- }
}
diff --git a/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java b/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java
index 6a878b983543..f376e8b1f9ed 100644
--- a/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java
+++ b/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java
@@ -29,13 +29,11 @@ import android.widget.CheckBox;
import com.android.internal.R;
import com.android.server.utils.AppInstallerUtil;
-public class UnsupportedCompileSdkDialog {
- private final AlertDialog mDialog;
- private final String mPackageName;
+class UnsupportedCompileSdkDialog extends AppWarnings.BaseDialog {
- public UnsupportedCompileSdkDialog(final AppWarnings manager, Context context,
+ UnsupportedCompileSdkDialog(final AppWarnings manager, Context context,
ApplicationInfo appInfo) {
- mPackageName = appInfo.packageName;
+ super(manager, appInfo.packageName);
final PackageManager pm = context.getPackageManager();
final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -72,16 +70,4 @@ public class UnsupportedCompileSdkDialog {
alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> manager.setPackageFlag(
mPackageName, AppWarnings.FLAG_HIDE_COMPILE_SDK, !isChecked));
}
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public void show() {
- mDialog.show();
- }
-
- public void dismiss() {
- mDialog.dismiss();
- }
}
diff --git a/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java b/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java
index 4a800c41fdeb..b11c22de4286 100644
--- a/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java
+++ b/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import com.android.internal.R;
-
import android.app.AlertDialog;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -27,13 +25,13 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
-public class UnsupportedDisplaySizeDialog {
- private final AlertDialog mDialog;
- private final String mPackageName;
+import com.android.internal.R;
- public UnsupportedDisplaySizeDialog(final AppWarnings manager, Context context,
+class UnsupportedDisplaySizeDialog extends AppWarnings.BaseDialog {
+
+ UnsupportedDisplaySizeDialog(final AppWarnings manager, Context context,
ApplicationInfo appInfo) {
- mPackageName = appInfo.packageName;
+ super(manager, appInfo.packageName);
final PackageManager pm = context.getPackageManager();
final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -63,16 +61,4 @@ public class UnsupportedDisplaySizeDialog {
alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> manager.setPackageFlag(
mPackageName, AppWarnings.FLAG_HIDE_DISPLAY_SIZE, !isChecked));
}
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public void show() {
- mDialog.show();
- }
-
- public void dismiss() {
- mDialog.dismiss();
- }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 1b39add3b421..9d039bd09a2f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -209,7 +209,8 @@ public class FlexibilityControllerTest {
public void testOnConstantsUpdated_DeadlineProximity() {
JobStatus js = createJobStatus("testDeadlineProximityConfig", createJob(0));
setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, Long.MAX_VALUE);
- mFlexibilityController.mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
+ mFlexibilityController.mFlexibilityAlarmQueue
+ .scheduleDropNumConstraintsAlarm(js, FROZEN_TIME);
assertEquals(0, js.getNumRequiredFlexibleConstraints());
}
@@ -336,26 +337,31 @@ public class FlexibilityControllerTest {
@Test
public void testCurPercent() {
long deadline = 1000;
+ long nowElapsed;
JobInfo.Builder jb = createJob(0).setOverrideDeadline(deadline);
JobStatus js = createJobStatus("time", jb);
assertEquals(FROZEN_TIME, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
assertEquals(deadline + FROZEN_TIME,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME));
+ nowElapsed = 600 + FROZEN_TIME;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(600 + FROZEN_TIME), ZoneOffset.UTC);
- assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
+ assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ nowElapsed = 1400;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(1400), ZoneOffset.UTC);
- assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
+ assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ nowElapsed = 950 + FROZEN_TIME;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(950 + FROZEN_TIME), ZoneOffset.UTC);
- assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
+ assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ nowElapsed = FROZEN_TIME;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(FROZEN_TIME), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
long delay = 100;
deadline = 1100;
jb = createJob(0).setOverrideDeadline(deadline).setMinimumLatency(delay);
@@ -366,18 +372,21 @@ public class FlexibilityControllerTest {
assertEquals(deadline + FROZEN_TIME,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME + delay));
+ nowElapsed = 600 + FROZEN_TIME + delay;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(600 + FROZEN_TIME + delay), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ nowElapsed = 1400;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(1400), ZoneOffset.UTC);
- assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
+ assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ nowElapsed = 950 + FROZEN_TIME + delay;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(950 + FROZEN_TIME + delay), ZoneOffset.UTC);
- assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
+ assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
}
@Test
@@ -491,19 +500,19 @@ public class FlexibilityControllerTest {
assertEquals(3, trackedJobs.get(2).size());
assertEquals(0, trackedJobs.get(3).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
assertEquals(0, trackedJobs.get(0).size());
assertEquals(1, trackedJobs.get(1).size());
assertEquals(2, trackedJobs.get(2).size());
assertEquals(0, trackedJobs.get(3).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(2, trackedJobs.get(2).size());
assertEquals(0, trackedJobs.get(3).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
assertEquals(0, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(2, trackedJobs.get(2).size());
@@ -515,24 +524,25 @@ public class FlexibilityControllerTest {
assertEquals(1, trackedJobs.get(2).size());
assertEquals(0, trackedJobs.get(3).size());
- flexTracker.resetJobNumDroppedConstraints(jobs[0]);
+ flexTracker.resetJobNumDroppedConstraints(jobs[0], FROZEN_TIME);
assertEquals(0, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(2, trackedJobs.get(2).size());
assertEquals(0, trackedJobs.get(3).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -2);
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -2, FROZEN_TIME);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(1, trackedJobs.get(2).size());
assertEquals(0, trackedJobs.get(3).size());
+ final long nowElapsed = ((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2)
+ + HOUR_IN_MILLIS);
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2)
- + HOUR_IN_MILLIS), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- flexTracker.resetJobNumDroppedConstraints(jobs[0]);
+ flexTracker.resetJobNumDroppedConstraints(jobs[0], nowElapsed);
assertEquals(0, trackedJobs.get(0).size());
assertEquals(1, trackedJobs.get(1).size());
assertEquals(1, trackedJobs.get(2).size());
@@ -615,13 +625,13 @@ public class FlexibilityControllerTest {
@Test
public void testSetConstraintSatisfied_Constraints() {
- mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false);
+ mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
assertFalse(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));
- mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, true);
+ mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, true, FROZEN_TIME);
assertTrue(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));
- mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false);
+ mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
assertFalse(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));
}
@@ -651,20 +661,21 @@ public class FlexibilityControllerTest {
createJobStatus(String.valueOf(i), jb), null);
}
}
- mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING, false);
- mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false);
- mFlexibilityController.setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, false);
+ mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING, false, FROZEN_TIME);
+ mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
+ mFlexibilityController.setConstraintSatisfied(
+ CONSTRAINT_BATTERY_NOT_LOW, false, FROZEN_TIME);
assertEquals(0, mFlexibilityController.mSatisfiedFlexibleConstraints);
for (int i = 0; i < constraintCombinations.length; i++) {
constraints = constraintCombinations[i];
mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING,
- (constraints & CONSTRAINT_CHARGING) != 0);
+ (constraints & CONSTRAINT_CHARGING) != 0, FROZEN_TIME);
mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE,
- (constraints & CONSTRAINT_IDLE) != 0);
+ (constraints & CONSTRAINT_IDLE) != 0, FROZEN_TIME);
mFlexibilityController.setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW,
- (constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0);
+ (constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0, FROZEN_TIME);
assertEquals(constraints, mFlexibilityController.mSatisfiedFlexibleConstraints);
synchronized (mFlexibilityController.mLock) {
@@ -679,6 +690,7 @@ public class FlexibilityControllerTest {
JobInfo.Builder jb = createJob(22).setOverrideDeadline(100L);
JobStatus js = createJobStatus("testResetJobNumDroppedConstraints", jb);
js.adjustNumRequiredFlexibleConstraints(3);
+ long nowElapsed;
mFlexibilityController.mFlexibilityTracker.add(js);
@@ -687,45 +699,51 @@ public class FlexibilityControllerTest {
assertEquals(1, mFlexibilityController
.mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size());
+
+ nowElapsed = 155L;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(155L), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1);
+ mFlexibilityController.mFlexibilityTracker
+ .adjustJobsRequiredConstraints(js, -1, nowElapsed);
assertEquals(2, js.getNumRequiredFlexibleConstraints());
assertEquals(1, js.getNumDroppedFlexibleConstraints());
assertEquals(1, mFlexibilityController
.mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size());
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
+ mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
assertEquals(2, js.getNumRequiredFlexibleConstraints());
assertEquals(1, js.getNumDroppedFlexibleConstraints());
assertEquals(1, mFlexibilityController
.mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size());
+ nowElapsed = 140L;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(140L), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
+ mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
assertEquals(3, js.getNumRequiredFlexibleConstraints());
assertEquals(0, js.getNumDroppedFlexibleConstraints());
assertEquals(1, mFlexibilityController
.mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size());
+ nowElapsed = 175L;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(175), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
+ mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
assertEquals(0, js.getNumRequiredFlexibleConstraints());
assertEquals(3, js.getNumDroppedFlexibleConstraints());
+ nowElapsed = 165L;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(165L), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
+ mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
assertEquals(1, js.getNumRequiredFlexibleConstraints());
assertEquals(2, js.getNumDroppedFlexibleConstraints());
@@ -745,12 +763,14 @@ public class FlexibilityControllerTest {
mFlexibilityController.maybeStartTrackingJobLocked(js, null);
+ final long nowElapsed = 150L;
JobSchedulerService.sElapsedRealtimeClock =
- Clock.fixed(Instant.ofEpochMilli(150L), ZoneOffset.UTC);
+ Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
mFlexibilityController.mPrefetchChangedListener.onPrefetchCacheUpdated(
jobs, js.getUserId(), js.getSourcePackageName(), Long.MAX_VALUE,
- 1150L + mFlexibilityController.mConstants.PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS);
+ 1150L + mFlexibilityController.mConstants.PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS,
+ nowElapsed);
assertEquals(150L,
(long) mFlexibilityController.mPrefetchLifeCycleStart
@@ -758,7 +778,7 @@ public class FlexibilityControllerTest {
assertEquals(150L, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
assertEquals(1150L,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, 150L));
- assertEquals(0, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
+ assertEquals(0, mFlexibilityController.getCurPercentOfLifecycleLocked(js, FROZEN_TIME));
assertEquals(650L, mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js));
assertEquals(3, js.getNumRequiredFlexibleConstraints());
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
index 969389c27e70..bb477b18d5fa 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
@@ -490,9 +490,9 @@ public class PrefetchControllerTest {
final PrefetchController.PrefetchChangedListener prefetchChangedListener =
new PrefetchController.PrefetchChangedListener() {
@Override
- public void onPrefetchCacheUpdated(
- ArraySet<JobStatus> jobs, int userId, String pkgName,
- long prevEstimatedLaunchTime, long newEstimatedLaunchTime) {
+ public void onPrefetchCacheUpdated(ArraySet<JobStatus> jobs,
+ int userId, String pkgName, long prevEstimatedLaunchTime,
+ long newEstimatedLaunchTime, long nowElapsed) {
onPrefetchCacheChangedCalled[0] = true;
}
};
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java
new file mode 100644
index 000000000000..903ed9082481
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
+import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
+import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.IBiometricService;
+import android.hardware.face.FaceSensorProperties;
+import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
+import android.hardware.face.IFaceService;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@SmallTest
+public class FaceServiceRegistryTest {
+
+ private static final int SENSOR_ID_1 = 1;
+ private static final int SENSOR_ID_2 = 2;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private IBiometricService mBiometricService;
+ @Mock
+ private IFaceService mFaceService;
+ @Mock
+ private ServiceProvider mProvider1;
+ @Mock
+ private ServiceProvider mProvider2;
+ @Captor
+ private ArgumentCaptor<Integer> mIdCaptor;
+ @Captor
+ private ArgumentCaptor<Integer> mStrengthCaptor;
+
+ private FaceSensorPropertiesInternal mProvider1Props;
+ private FaceSensorPropertiesInternal mProvider2Props;
+ private FaceServiceRegistry mRegistry;
+
+ @Before
+ public void setup() {
+ mProvider1Props = new FaceSensorPropertiesInternal(SENSOR_ID_1,
+ STRENGTH_WEAK, 5 /* maxEnrollmentsPerUser */,
+ List.of(), FaceSensorProperties.TYPE_RGB,
+ true /* supportsFace Detection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresHardwareAuthToken */);
+ mProvider2Props = new FaceSensorPropertiesInternal(SENSOR_ID_2,
+ STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
+ List.of(), FaceSensorProperties.TYPE_IR,
+ true /* supportsFace Detection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresHardwareAuthToken */);
+
+ when(mProvider1.getSensorProperties()).thenReturn(List.of(mProvider1Props));
+ when(mProvider1.containsSensor(eq(SENSOR_ID_1))).thenReturn(true);
+ when(mProvider2.getSensorProperties()).thenReturn(List.of(mProvider2Props));
+ when(mProvider2.containsSensor(eq(SENSOR_ID_2))).thenReturn(true);
+ mRegistry = new FaceServiceRegistry(mFaceService, () -> mBiometricService);
+ }
+
+ @Test
+ public void registersAllProviders() throws Exception {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(mRegistry.getProviders()).containsExactly(mProvider1, mProvider2);
+ assertThat(mRegistry.getAllProperties()).containsExactly(mProvider1Props, mProvider2Props);
+ verify(mBiometricService, times(2)).registerAuthenticator(
+ mIdCaptor.capture(), eq(TYPE_FACE), mStrengthCaptor.capture(), any());
+ assertThat(mIdCaptor.getAllValues()).containsExactly(SENSOR_ID_1, SENSOR_ID_2);
+ assertThat(mStrengthCaptor.getAllValues())
+ .containsExactly(BIOMETRIC_WEAK, BIOMETRIC_STRONG);
+ }
+
+ @Test
+ public void getsProviderById() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
+ assertThat(mRegistry.getProviderForSensor(SENSOR_ID_2)).isSameInstanceAs(mProvider2);
+ assertThat(mRegistry.getProviderForSensor(500)).isNull();
+ }
+
+ @Test
+ public void getsSingleProvider() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1));
+
+ assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1);
+ assertThat(mRegistry.getProviders()).containsExactly(mProvider1);
+ assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
+ }
+
+ @Test
+ public void getSingleProviderFindsFirstWhenMultiple() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1);
+ }
+
+ @Test
+ public void registersListenerBeforeAllRegistered() {
+ final List<FaceSensorPropertiesInternal> all = new ArrayList<>();
+ mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FaceSensorPropertiesInternal> sensors) {
+ all.addAll(sensors);
+ }
+ });
+
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
+ }
+
+ @Test
+ public void registersListenerAfterAllRegistered() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ final List<FaceSensorPropertiesInternal> all = new ArrayList<>();
+ mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FaceSensorPropertiesInternal> sensors) {
+ all.addAll(sensors);
+ }
+ });
+
+ assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
index 5f88c99b1d1e..0e30782eaece 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.fingerprint;
+import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
+
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -24,38 +26,73 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricStateListener;
+import android.hardware.biometrics.SensorPropertiesInternal;
+import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.BiometricServiceProvider;
import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.EnrollClient;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
@Presubmit
@SmallTest
public class BiometricStateCallbackTest {
- private BiometricStateCallback mCallback;
+ private static final int USER_ID = 10;
+ private static final int SENSOR_ID = 2;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private BiometricStateCallback<FakeProvider, SensorPropertiesInternal> mCallback;
@Mock
- BiometricStateListener mBiometricStateListener;
+ private UserManager mUserManager;
+ @Mock
+ private BiometricStateListener mBiometricStateListener;
+ @Mock
+ private FakeProvider mFakeProvider;
+
+ private SensorPropertiesInternal mFakeProviderProps;
@Before
public void setup() {
- MockitoAnnotations.initMocks(this);
-
- mCallback = new BiometricStateCallback();
+ mFakeProviderProps = new SensorPropertiesInternal(SENSOR_ID, STRENGTH_STRONG,
+ 5 /* maxEnrollmentsPerUser */, List.of(),
+ false /* resetLockoutRequiresHardwareAuthToken */,
+ false /* resetLockoutRequiresChallenge */);
+ when(mFakeProvider.getSensorProperties()).thenReturn(List.of(mFakeProviderProps));
+ when(mFakeProvider.getSensorProperties(eq(SENSOR_ID))).thenReturn(mFakeProviderProps);
+ when(mFakeProvider.hasEnrollments(eq(SENSOR_ID), eq(USER_ID))).thenReturn(true);
+ when(mUserManager.getAliveUsers()).thenReturn(
+ List.of(new UserInfo(USER_ID, "name", 0)));
+
+ mCallback = new BiometricStateCallback<>(mUserManager);
mCallback.registerBiometricStateListener(mBiometricStateListener);
}
@Test
+ public void startNotifiesEnrollments() {
+ mCallback.start(List.of(mFakeProvider));
+
+ verify(mBiometricStateListener).onEnrollmentsChanged(eq(USER_ID), eq(SENSOR_ID), eq(true));
+ }
+
+ @Test
public void testNoEnrollmentsToEnrollments_callbackNotified() {
testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */,
true /* expectCallback */, true /* expectedCallbackValue */);
@@ -102,4 +139,6 @@ public class BiometricStateCallbackTest {
verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
anyBoolean());
}
+
+ private interface FakeProvider extends BiometricServiceProvider<SensorPropertiesInternal> {}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java
new file mode 100644
index 000000000000..13c3f64fec93
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint;
+
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
+import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
+import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.IBiometricService;
+import android.hardware.fingerprint.FingerprintSensorProperties;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
+import android.hardware.fingerprint.IFingerprintService;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@SmallTest
+public class FingerprintServiceRegistryTest {
+
+ private static final int SENSOR_ID_1 = 1;
+ private static final int SENSOR_ID_2 = 2;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private IBiometricService mBiometricService;
+ @Mock
+ private IFingerprintService mFingerprintService;
+ @Mock
+ private ServiceProvider mProvider1;
+ @Mock
+ private ServiceProvider mProvider2;
+ @Captor
+ private ArgumentCaptor<Integer> mIdCaptor;
+ @Captor
+ private ArgumentCaptor<Integer> mStrengthCaptor;
+
+ private FingerprintSensorPropertiesInternal mProvider1Props;
+ private FingerprintSensorPropertiesInternal mProvider2Props;
+ private FingerprintServiceRegistry mRegistry;
+
+ @Before
+ public void setup() {
+ mProvider1Props = new FingerprintSensorPropertiesInternal(SENSOR_ID_1,
+ STRENGTH_WEAK, 5 /* maxEnrollmentsPerUser */,
+ List.of(), FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
+ false /* resetLockoutRequiresHardwareAuthToken */);
+ mProvider2Props = new FingerprintSensorPropertiesInternal(SENSOR_ID_2,
+ STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
+ List.of(), FingerprintSensorProperties.TYPE_UNKNOWN,
+ false /* resetLockoutRequiresHardwareAuthToken */);
+
+ when(mProvider1.getSensorProperties()).thenReturn(List.of(mProvider1Props));
+ when(mProvider1.containsSensor(eq(SENSOR_ID_1))).thenReturn(true);
+ when(mProvider2.getSensorProperties()).thenReturn(List.of(mProvider2Props));
+ when(mProvider2.containsSensor(eq(SENSOR_ID_2))).thenReturn(true);
+ mRegistry = new FingerprintServiceRegistry(mFingerprintService, () -> mBiometricService);
+ }
+
+ @Test
+ public void registersAllProviders() throws Exception {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(mRegistry.getProviders()).containsExactly(mProvider1, mProvider2);
+ assertThat(mRegistry.getAllProperties()).containsExactly(mProvider1Props, mProvider2Props);
+ verify(mBiometricService, times(2)).registerAuthenticator(
+ mIdCaptor.capture(), eq(TYPE_FINGERPRINT), mStrengthCaptor.capture(), any());
+ assertThat(mIdCaptor.getAllValues()).containsExactly(SENSOR_ID_1, SENSOR_ID_2);
+ assertThat(mStrengthCaptor.getAllValues())
+ .containsExactly(BIOMETRIC_WEAK, BIOMETRIC_STRONG);
+ }
+
+ @Test
+ public void getsProviderById() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
+ assertThat(mRegistry.getProviderForSensor(SENSOR_ID_2)).isSameInstanceAs(mProvider2);
+ assertThat(mRegistry.getProviderForSensor(500)).isNull();
+ }
+
+ @Test
+ public void getsSingleProvider() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1));
+
+ assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1);
+ assertThat(mRegistry.getProviders()).containsExactly(mProvider1);
+ assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
+ }
+
+ @Test
+ public void getSingleProviderFindsFirstWhenMultiple() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1);
+ }
+
+ @Test
+ public void registersListenerBeforeAllRegistered() {
+ final List<FingerprintSensorPropertiesInternal> all = new ArrayList<>();
+ mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FingerprintSensorPropertiesInternal> sensors) {
+ all.addAll(sensors);
+ }
+ });
+
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
+ }
+
+ @Test
+ public void registersListenerAfterAllRegistered() {
+ mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
+
+ final List<FingerprintSensorPropertiesInternal> all = new ArrayList<>();
+ mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FingerprintSensorPropertiesInternal> sensors) {
+ all.addAll(sensors);
+ }
+ });
+
+ assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
index ca3677e3b5ff..a4048a27dfb5 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
@@ -32,7 +32,8 @@ import android.hardware.biometrics.fingerprint.FingerprintSensorType;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.SensorLocation;
import android.hardware.biometrics.fingerprint.SensorProps;
-import android.os.RemoteException;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.testing.TestableContext;
@@ -52,6 +53,8 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
@Presubmit
@SmallTest
@@ -94,9 +97,12 @@ public class FingerprintServiceTest {
mContext.getTestablePermissions().setPermission(
USE_BIOMETRIC_INTERNAL, PackageManager.PERMISSION_GRANTED);
+ }
+ private void initServiceWith(String... aidlInstances) {
mService = new FingerprintService(mContext, mBiometricContext,
() -> mIBiometricService,
+ () -> aidlInstances,
(fqName) -> {
if (fqName.endsWith(NAME_DEFAULT)) return mIFingerprintDefault;
if (fqName.endsWith(NAME_VIRTUAL)) return mIFingerprintVirtual;
@@ -105,29 +111,50 @@ public class FingerprintServiceTest {
}
@Test
- public void registerAuthenticators_defaultOnly() throws RemoteException {
- mService.registerAuthenticatorsForService(List.of(NAME_DEFAULT, NAME_VIRTUAL), List.of());
+ public void registerAuthenticators_defaultOnly() throws Exception {
+ initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
+
+ mService.mServiceWrapper.registerAuthenticators(List.of());
+ waitForRegistration();
verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT), anyInt(), anyInt(), any());
}
@Test
- public void registerAuthenticators_virtualOnly() throws RemoteException {
+ public void registerAuthenticators_virtualOnly() throws Exception {
+ initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1);
- mService.registerAuthenticatorsForService(List.of(NAME_DEFAULT, NAME_VIRTUAL), List.of());
+ mService.mServiceWrapper.registerAuthenticators(List.of());
+ waitForRegistration();
verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
}
@Test
- public void registerAuthenticators_virtualAlwaysWhenNoOther() throws RemoteException {
- mService.registerAuthenticatorsForService(List.of(NAME_VIRTUAL), List.of());
+ public void registerAuthenticators_virtualAlwaysWhenNoOther() throws Exception {
+ initServiceWith(NAME_VIRTUAL);
+
+ mService.mServiceWrapper.registerAuthenticators(List.of());
+ waitForRegistration();
verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
}
+ private void waitForRegistration() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mService.mServiceWrapper.addAuthenticatorsRegisteredCallback(
+ new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ List<FingerprintSensorPropertiesInternal> sensors) {
+ latch.countDown();
+ }
+ });
+ latch.await(5, TimeUnit.SECONDS);
+ }
+
private static SensorProps createProps(int id, byte strength, byte type) {
final SensorProps props = new SensorProps();
props.commonProps = new CommonProps();
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index 5c9348525861..61a7f3853746 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -28,7 +28,6 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BatteryStatsHistory;
-import com.android.internal.os.Clock;
import org.junit.Before;
import org.junit.Test;
@@ -50,14 +49,13 @@ public class BatteryStatsHistoryTest {
private final Parcel mHistoryBuffer = Parcel.obtain();
private File mSystemDir;
private File mHistoryDir;
- private final Clock mClock = new MockClock();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = InstrumentationRegistry.getContext();
mSystemDir = context.getDataDir();
- mHistoryDir = new File(mSystemDir, "battery-history");
+ mHistoryDir = new File(mSystemDir, BatteryStatsHistory.HISTORY_DIR);
String[] files = mHistoryDir.list();
if (files != null) {
for (int i = 0; i < files.length; i++) {
@@ -69,8 +67,8 @@ public class BatteryStatsHistoryTest {
@Test
public void testConstruct() {
- BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
- null, mClock);
+ BatteryStatsHistory history =
+ new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
createActiveFile(history);
verifyFileNumbers(history, Arrays.asList(0));
verifyActiveFile(history, "0.bin");
@@ -78,8 +76,8 @@ public class BatteryStatsHistoryTest {
@Test
public void testStartNextFile() {
- BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
- null, mClock);
+ BatteryStatsHistory history =
+ new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
List<Integer> fileList = new ArrayList<>();
fileList.add(0);
createActiveFile(history);
@@ -116,13 +114,13 @@ public class BatteryStatsHistoryTest {
assertEquals(0, history.getHistoryUsedSize());
// create a new BatteryStatsHistory object, it will pick up existing history files.
- BatteryStatsHistory history2 = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
- null, mClock);
- // verify constructor can pick up all files from file system.
+ BatteryStatsHistory history2 =
+ new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
+ // verify construct can pick up all files from file system.
verifyFileNumbers(history2, fileList);
verifyActiveFile(history2, "33.bin");
- history2.reset();
+ history2.resetAllFiles();
createActiveFile(history2);
// verify all existing files are deleted.
for (int i = 2; i < 33; ++i) {
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 570b2ee617f5..713e78638b95 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -63,7 +63,6 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
MockBatteryStatsImpl(Clock clock, File historyDirectory) {
super(clock, historyDirectory);
initTimersAndCounters();
- setMaxHistoryBuffer(128 * 1024);
setExternalStatsSyncLocked(mExternalStatsSync);
informThatAllExternalStatsAreFlushed();
@@ -105,6 +104,12 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
return mForceOnBattery ? true : super.isOnBattery();
}
+ public void forceRecordAllHistory() {
+ mHaveBatteryLevel = true;
+ mRecordingHistory = true;
+ mRecordAllHistory = true;
+ }
+
public TimeBase getOnBatteryBackgroundTimeBase(int uid) {
return getUidStatsLocked(uid).mOnBatteryBackgroundTimeBase;
}
@@ -196,14 +201,12 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
@GuardedBy("this")
public MockBatteryStatsImpl setMaxHistoryFiles(int maxHistoryFiles) {
mConstants.MAX_HISTORY_FILES = maxHistoryFiles;
- mConstants.onChange();
return this;
}
@GuardedBy("this")
public MockBatteryStatsImpl setMaxHistoryBuffer(int maxHistoryBuffer) {
mConstants.MAX_HISTORY_BUFFER = maxHistoryBuffer;
- mConstants.onChange();
return this;
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index be7fb7315955..8df3548465bd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -21,7 +21,6 @@ import android.platform.test.annotations.Presubmit
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.traces.common.ComponentMatcher
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index 472a0fa376bf..eddb55346af8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.IComponentMatcher
/**
@@ -28,7 +28,7 @@ import com.android.server.wm.traces.common.IComponentMatcher
*/
fun FlickerTestParameter.statusBarWindowIsAlwaysVisible() {
assertWm {
- this.isAboveAppWindowVisible(ComponentMatcher.STATUS_BAR)
+ this.isAboveAppWindowVisible(ComponentNameMatcher.STATUS_BAR)
}
}
@@ -38,7 +38,7 @@ fun FlickerTestParameter.statusBarWindowIsAlwaysVisible() {
*/
fun FlickerTestParameter.navBarWindowIsAlwaysVisible() {
assertWm {
- this.isAboveAppWindowVisible(ComponentMatcher.NAV_BAR)
+ this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
}
}
@@ -48,10 +48,10 @@ fun FlickerTestParameter.navBarWindowIsAlwaysVisible() {
*/
fun FlickerTestParameter.navBarWindowIsVisibleAtStartAndEnd() {
assertWmStart {
- this.isAboveAppWindowVisible(ComponentMatcher.NAV_BAR)
+ this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
}
assertWmEnd {
- this.isAboveAppWindowVisible(ComponentMatcher.NAV_BAR)
+ this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
}
}
@@ -61,7 +61,7 @@ fun FlickerTestParameter.navBarWindowIsVisibleAtStartAndEnd() {
*/
fun FlickerTestParameter.taskBarWindowIsAlwaysVisible() {
assertWm {
- this.isAboveAppWindowVisible(ComponentMatcher.TASK_BAR)
+ this.isAboveAppWindowVisible(ComponentNameMatcher.TASK_BAR)
}
}
@@ -71,7 +71,7 @@ fun FlickerTestParameter.taskBarWindowIsAlwaysVisible() {
*/
fun FlickerTestParameter.taskBarWindowIsVisibleAtEnd() {
assertWmEnd {
- this.isAboveAppWindowVisible(ComponentMatcher.TASK_BAR)
+ this.isAboveAppWindowVisible(ComponentNameMatcher.TASK_BAR)
}
}
@@ -114,10 +114,10 @@ fun FlickerTestParameter.entireScreenCovered(allStates: Boolean = true) {
*/
fun FlickerTestParameter.navBarLayerIsVisibleAtStartAndEnd() {
assertLayersStart {
- this.isVisible(ComponentMatcher.NAV_BAR)
+ this.isVisible(ComponentNameMatcher.NAV_BAR)
}
assertLayersEnd {
- this.isVisible(ComponentMatcher.NAV_BAR)
+ this.isVisible(ComponentNameMatcher.NAV_BAR)
}
}
@@ -136,7 +136,7 @@ fun FlickerTestParameter.taskBarLayerIsVisibleAtStartAndEnd() {
*/
fun FlickerTestParameter.taskBarLayerIsVisibleAtStart() {
assertLayersStart {
- this.isVisible(ComponentMatcher.TASK_BAR)
+ this.isVisible(ComponentNameMatcher.TASK_BAR)
}
}
@@ -146,7 +146,7 @@ fun FlickerTestParameter.taskBarLayerIsVisibleAtStart() {
*/
fun FlickerTestParameter.taskBarLayerIsVisibleAtEnd() {
assertLayersEnd {
- this.isVisible(ComponentMatcher.TASK_BAR)
+ this.isVisible(ComponentNameMatcher.TASK_BAR)
}
}
@@ -156,10 +156,10 @@ fun FlickerTestParameter.taskBarLayerIsVisibleAtEnd() {
*/
fun FlickerTestParameter.statusBarLayerIsVisibleAtStartAndEnd() {
assertLayersStart {
- this.isVisible(ComponentMatcher.STATUS_BAR)
+ this.isVisible(ComponentNameMatcher.STATUS_BAR)
}
assertLayersEnd {
- this.isVisible(ComponentMatcher.STATUS_BAR)
+ this.isVisible(ComponentNameMatcher.STATUS_BAR)
}
}
@@ -171,7 +171,7 @@ fun FlickerTestParameter.navBarLayerPositionAtStart() {
assertLayersStart {
val display = this.entry.displays.firstOrNull { !it.isVirtual }
?: error("There is no display!")
- this.visibleRegion(ComponentMatcher.NAV_BAR)
+ this.visibleRegion(ComponentNameMatcher.NAV_BAR)
.coversExactly(WindowUtils.getNavigationBarPosition(display, isGesturalNavigation))
}
}
@@ -184,7 +184,7 @@ fun FlickerTestParameter.navBarLayerPositionAtEnd() {
assertLayersEnd {
val display = this.entry.displays.minByOrNull { it.id }
?: throw RuntimeException("There is no display!")
- this.visibleRegion(ComponentMatcher.NAV_BAR)
+ this.visibleRegion(ComponentNameMatcher.NAV_BAR)
.coversExactly(WindowUtils.getNavigationBarPosition(display, isGesturalNavigation))
}
}
@@ -206,7 +206,7 @@ fun FlickerTestParameter.statusBarLayerPositionAtStart() {
assertLayersStart {
val display = this.entry.displays.minByOrNull { it.id }
?: throw RuntimeException("There is no display!")
- this.visibleRegion(ComponentMatcher.STATUS_BAR)
+ this.visibleRegion(ComponentNameMatcher.STATUS_BAR)
.coversExactly(WindowUtils.getStatusBarPosition(display))
}
}
@@ -219,7 +219,7 @@ fun FlickerTestParameter.statusBarLayerPositionAtEnd() {
assertLayersEnd {
val display = this.entry.displays.minByOrNull { it.id }
?: throw RuntimeException("There is no display!")
- this.visibleRegion(ComponentMatcher.STATUS_BAR)
+ this.visibleRegion(ComponentNameMatcher.STATUS_BAR)
.coversExactly(WindowUtils.getStatusBarPosition(display))
}
}
@@ -244,7 +244,7 @@ fun FlickerTestParameter.snapshotStartingWindowLayerCoversExactlyOnApp(
invoke("snapshotStartingWindowLayerCoversExactlyOnApp") {
val snapshotLayers = it.subjects.filter { subject ->
subject.name.contains(
- ComponentMatcher.SNAPSHOT.toLayerName()) && subject.isVisible
+ ComponentNameMatcher.SNAPSHOT.toLayerName()) && subject.isVisible
}
// Verify the size of snapshotRegion covers appVisibleRegion exactly in animation.
if (snapshotLayers.isNotEmpty()) {
@@ -291,10 +291,10 @@ fun FlickerTestParameter.replacesLayer(
val assertion = this.isVisible(originalLayer)
if (ignoreEntriesWithRotationLayer) {
- assertion.then().isVisible(ComponentMatcher.ROTATION, isOptional = true)
+ assertion.then().isVisible(ComponentNameMatcher.ROTATION, isOptional = true)
}
if (ignoreSnapshot) {
- assertion.then().isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ assertion.then().isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
}
if (ignoreSplashscreen) {
assertion.then().isSplashScreenVisibleFor(newLayer, isOptional = true)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index 7ff093474399..cb197cdf04d3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -24,7 +24,7 @@ import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.replacesLayer
-import com.android.server.wm.traces.common.ComponentMatcher.Companion.LAUNCHER
+import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.LAUNCHER
import org.junit.Test
/**
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index af3a8c502008..b8fe9f9df882 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -26,7 +26,7 @@ import androidx.window.extensions.WindowExtensions
import androidx.window.extensions.WindowExtensionsProvider
import androidx.window.extensions.embedding.ActivityEmbeddingComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.windowmanager.WindowManagerState.Companion.STATE_RESUMED
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
@@ -35,7 +35,7 @@ import org.junit.Assume.assumeNotNull
class ActivityEmbeddingAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.ACTIVITY_EMBEDDING_LAUNCHER_NAME,
- component: IComponentMatcher = MAIN_ACTIVITY_COMPONENT,
+ component: ComponentNameMatcher = MAIN_ACTIVITY_COMPONENT,
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
index bd0ae4d47383..34f9ce43b4bc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
@@ -21,12 +21,11 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.provider.MediaStore
-import com.android.server.wm.traces.common.ComponentMatcher
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
class CameraAppHelper @JvmOverloads constructor(
- instrumentation: Instrumentation,
- private val pkgManager: PackageManager = instrumentation.context.packageManager
+ instrumentation: Instrumentation,
+ pkgManager: PackageManager = instrumentation.context.packageManager
) : StandardAppHelper(instrumentation, getCameraLauncherName(pkgManager),
getCameraComponent(pkgManager)){
companion object{
@@ -40,9 +39,9 @@ class CameraAppHelper @JvmOverloads constructor(
?: error("unable to resolve camera activity")
}
- private fun getCameraComponent(pkgManager: PackageManager): IComponentMatcher {
+ private fun getCameraComponent(pkgManager: PackageManager): ComponentNameMatcher {
val resolveInfo = getResolveInfo(pkgManager)
- return ComponentMatcher(resolveInfo.activityInfo.packageName,
+ return ComponentNameMatcher(resolveInfo.activityInfo.packageName,
className = resolveInfo.activityInfo.name)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
index 28858d4843a1..b696fc30c19f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
@@ -20,13 +20,13 @@ import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class FixedOrientationAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.PORTRAIT_ONLY_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.PORTRAIT_ONLY_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
index f536a151d8fd..e01cceb5d636 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
@@ -23,7 +23,7 @@ import android.view.WindowInsets.Type.statusBars
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import java.util.regex.Pattern
@@ -33,7 +33,7 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
private val rotation: Int,
private val imePackageName: String = IME_PACKAGE,
launcherName: String = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent()
) : ImeAppHelper(instr, launcherName, component) {
override fun openIME(wmHelper: WindowManagerStateHelper) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index db64c4769715..b672b1bc0da5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -22,14 +22,14 @@ import android.support.test.launcherhelper.LauncherStrategyFactory
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
open class ImeAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.IME_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.IME_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
index f74054ea4459..df47e9dfacd9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
@@ -20,16 +20,14 @@ import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class ImeEditorPopupDialogAppHelper @JvmOverloads constructor(
instr: Instrumentation,
- private val rotation: Int,
- private val imePackageName: String = IME_PACKAGE,
launcherName: String = ActivityOptions.EDITOR_POPUP_DIALOG_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
) : ImeAppHelper(instr, launcherName, component) {
override fun openIME(wmHelper: WindowManagerStateHelper) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
index 7f8b5633391b..d3945c1749e3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
@@ -20,13 +20,13 @@ import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class ImeStateInitializeHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.IME_ACTIVITY_INITIALIZE_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.IME_ACTIVITY_INITIALIZE_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
index 149576e4ec1d..9fb574cf1c04 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
@@ -23,14 +23,14 @@ import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class NewTasksAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.LAUNCH_NEW_TASK_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
index a9769d01caff..a1dbeeaef5cc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
@@ -20,13 +20,13 @@ import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class NonResizeableAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.NON_RESIZEABLE_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.NON_RESIZEABLE_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
index 50d036c4450f..b031a4523ab0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
@@ -22,14 +22,14 @@ import android.support.test.launcherhelper.LauncherStrategyFactory
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class NotificationAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.NOTIFICATION_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.NOTIFICATION_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
index 459ca5b3208f..6d466d72d7dd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
@@ -20,13 +20,13 @@ import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class SeamlessRotationAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SEAMLESS_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.SEAMLESS_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
index 4952dbaeb551..804ab3864591 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
@@ -20,13 +20,13 @@ import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class ShowWhenLockedAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SHOW_WHEN_LOCKED_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.SHOW_WHEN_LOCKED_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
index 6bddcac21a4d..5da273a7f1dc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
@@ -20,13 +20,13 @@ import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class SimpleAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SIMPLE_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
index a17344f3879b..060e9af4a51c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
@@ -23,14 +23,14 @@ import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class TwoActivitiesAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.BUTTON_ACTIVITY_LAUNCHER_NAME,
- component: IComponentMatcher =
+ component: ComponentNameMatcher =
ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index 6b8fde21e53d..f6f3f58f29cb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -83,7 +83,7 @@ class CloseImeAutoOpenWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest
@Test
fun imeLayerVisibleStart() {
testSpec.assertLayersStart {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
}
}
@@ -91,7 +91,7 @@ class CloseImeAutoOpenWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest
@Test
fun imeLayerInvisibleEnd() {
testSpec.assertLayersEnd {
- this.isInvisible(ComponentMatcher.IME)
+ this.isInvisible(ComponentNameMatcher.IME)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index a92ecb953a01..52f561ec4497 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -92,7 +92,7 @@ class CloseImeAutoOpenWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTes
@Test
fun imeLayerVisibleStart() {
testSpec.assertLayersStart {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
}
}
@@ -100,7 +100,7 @@ class CloseImeAutoOpenWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTes
@Test
fun imeLayerInvisibleEnd() {
testSpec.assertLayersEnd {
- this.isInvisible(ComponentMatcher.IME)
+ this.isInvisible(ComponentNameMatcher.IME)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
index 0e4d1dd009e2..c6e25d3de4cd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
@@ -28,7 +28,7 @@ import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeEditorPopupDialogAppHelper
import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,7 +41,7 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group4
class CloseImeEditorPopupDialogTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
- private val imeTestApp = ImeEditorPopupDialogAppHelper(instrumentation, testSpec.startRotation)
+ private val imeTestApp = ImeEditorPopupDialogAppHelper(instrumentation)
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
@@ -102,12 +102,12 @@ class CloseImeEditorPopupDialogTest(testSpec: FlickerTestParameter) : BaseTest(t
@Test
fun imeLayerAndImeSnapshotVisibleOnScreen() {
testSpec.assertLayers {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
.then()
- .isVisible(ComponentMatcher.IME_SNAPSHOT)
+ .isVisible(ComponentNameMatcher.IME_SNAPSHOT)
.then()
- .isInvisible(ComponentMatcher.IME_SNAPSHOT, isOptional = true)
- .isInvisible(ComponentMatcher.IME)
+ .isInvisible(ComponentNameMatcher.IME_SNAPSHOT, isOptional = true)
+ .isInvisible(ComponentNameMatcher.IME)
}
}
@@ -118,7 +118,7 @@ class CloseImeEditorPopupDialogTest(testSpec: FlickerTestParameter) : BaseTest(t
this.invoke("imeSnapshotAssociatedOnAppVisibleRegion") {
val imeSnapshotLayers = it.subjects.filter { subject ->
subject.name.contains(
- ComponentMatcher.IME_SNAPSHOT.toLayerName()
+ ComponentNameMatcher.IME_SNAPSHOT.toLayerName()
) && subject.isVisible
}
if (imeSnapshotLayers.isNotEmpty()) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index 452aa63e2bf9..23bd2200397a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -73,9 +73,9 @@ class CloseImeWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest(testSpe
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(
- ComponentMatcher.IME,
- ComponentMatcher.SPLASH_SCREEN,
- ComponentMatcher.SNAPSHOT))
+ ComponentNameMatcher.IME,
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT))
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index 856df260c2be..8ce184072d32 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -78,9 +78,9 @@ class CloseImeWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTest(testSp
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry(
listOf(
- ComponentMatcher.IME,
- ComponentMatcher.SPLASH_SCREEN,
- ComponentMatcher.SNAPSHOT
+ ComponentNameMatcher.IME,
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT
)
)
}
@@ -93,8 +93,8 @@ class CloseImeWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTest(testSp
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
listOf(
- ComponentMatcher.IME,
- ComponentMatcher.SPLASH_SCREEN
+ ComponentNameMatcher.IME,
+ ComponentNameMatcher.SPLASH_SCREEN
)
)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 19cab3c20dae..9c99d966e345 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -18,52 +18,52 @@
package com.android.server.wm.flicker.ime
import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
fun FlickerTestParameter.imeLayerBecomesVisible() {
assertLayers {
- this.isInvisible(ComponentMatcher.IME)
+ this.isInvisible(ComponentNameMatcher.IME)
.then()
- .isVisible(ComponentMatcher.IME)
+ .isVisible(ComponentNameMatcher.IME)
}
}
fun FlickerTestParameter.imeLayerBecomesInvisible() {
assertLayers {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
.then()
- .isInvisible(ComponentMatcher.IME)
+ .isInvisible(ComponentNameMatcher.IME)
}
}
fun FlickerTestParameter.imeWindowIsAlwaysVisible(rotatesScreen: Boolean = false) {
if (rotatesScreen) {
assertWm {
- this.isNonAppWindowVisible(ComponentMatcher.IME)
+ this.isNonAppWindowVisible(ComponentNameMatcher.IME)
.then()
- .isNonAppWindowInvisible(ComponentMatcher.IME)
+ .isNonAppWindowInvisible(ComponentNameMatcher.IME)
.then()
- .isNonAppWindowVisible(ComponentMatcher.IME)
+ .isNonAppWindowVisible(ComponentNameMatcher.IME)
}
} else {
assertWm {
- this.isNonAppWindowVisible(ComponentMatcher.IME)
+ this.isNonAppWindowVisible(ComponentNameMatcher.IME)
}
}
}
fun FlickerTestParameter.imeWindowBecomesVisible() {
assertWm {
- this.isNonAppWindowInvisible(ComponentMatcher.IME)
+ this.isNonAppWindowInvisible(ComponentNameMatcher.IME)
.then()
- .isNonAppWindowVisible(ComponentMatcher.IME)
+ .isNonAppWindowVisible(ComponentNameMatcher.IME)
}
}
fun FlickerTestParameter.imeWindowBecomesInvisible() {
assertWm {
- this.isNonAppWindowVisible(ComponentMatcher.IME)
+ this.isNonAppWindowVisible(ComponentNameMatcher.IME)
.then()
- .isNonAppWindowInvisible(ComponentMatcher.IME)
+ .isNonAppWindowInvisible(ComponentNameMatcher.IME)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
index 4569a5b4910e..a04a50f02c26 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
@@ -30,7 +30,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
@@ -101,7 +101,7 @@ class LaunchAppShowImeAndDialogThemeAppTest(
@Test
fun imeLayerExistsEnd() {
testSpec.assertLayersEnd {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
}
}
@@ -112,7 +112,7 @@ class LaunchAppShowImeAndDialogThemeAppTest(
@Test
fun imeSnapshotNotVisible() {
testSpec.assertLayers {
- this.isInvisible(ComponentMatcher.IME_SNAPSHOT)
+ this.isInvisible(ComponentNameMatcher.IME_SNAPSHOT)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
index 977719c5f670..04e4bc94de9c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
@@ -28,7 +28,7 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import com.android.server.wm.flicker.helpers.ImeStateInitializeHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -114,7 +114,7 @@ class LaunchAppShowImeOnStartTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun imeLayerNotExistsStart() {
testSpec.assertLayersStart {
- this.isInvisible(ComponentMatcher.IME)
+ this.isInvisible(ComponentNameMatcher.IME)
}
}
@@ -125,7 +125,7 @@ class LaunchAppShowImeOnStartTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun imeLayerExistsEnd() {
testSpec.assertLayersEnd {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
index 16cf22abecc2..9475734ef3f5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
@@ -31,7 +31,7 @@ import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
import com.android.server.wm.flicker.statusBarLayerIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.WindowManagerConditionsFactory
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume
@@ -138,10 +138,10 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
Assume.assumeTrue(testSpec.isGesturalNavigation)
Assume.assumeTrue(isShellTransitionsEnabled)
testSpec.assertLayersStart {
- this.isVisible(ComponentMatcher.NAV_BAR)
+ this.isVisible(ComponentNameMatcher.NAV_BAR)
}
testSpec.assertLayersEnd {
- this.isInvisible(ComponentMatcher.NAV_BAR)
+ this.isInvisible(ComponentNameMatcher.NAV_BAR)
}
}
@@ -156,10 +156,10 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
Assume.assumeTrue(testSpec.isGesturalNavigation)
Assume.assumeFalse(testSpec.isTablet)
testSpec.assertLayersStart {
- this.isVisible(ComponentMatcher.STATUS_BAR)
+ this.isVisible(ComponentNameMatcher.STATUS_BAR)
}
testSpec.assertLayersEnd {
- this.isInvisible(ComponentMatcher.STATUS_BAR)
+ this.isInvisible(ComponentNameMatcher.STATUS_BAR)
}
}
@@ -215,10 +215,10 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
Assume.assumeFalse(testSpec.isTablet)
Assume.assumeTrue(isShellTransitionsEnabled)
testSpec.assertLayersStart {
- this.isVisible(ComponentMatcher.STATUS_BAR)
+ this.isVisible(ComponentNameMatcher.STATUS_BAR)
}
testSpec.assertLayersEnd {
- this.isInvisible(ComponentMatcher.STATUS_BAR)
+ this.isInvisible(ComponentNameMatcher.STATUS_BAR)
}
}
@@ -235,7 +235,7 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun imeLayerIsVisibleAndAssociatedWithAppWidow() {
testSpec.assertLayersStart {
- isVisible(ComponentMatcher.IME).visibleRegion(ComponentMatcher.IME)
+ isVisible(ComponentNameMatcher.IME).visibleRegion(ComponentNameMatcher.IME)
.coversAtMost(
isVisible(imeTestApp)
.visibleRegion(imeTestApp).region
@@ -243,10 +243,10 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
}
testSpec.assertLayers {
this.invoke("imeLayerIsVisibleAndAlignAppWidow") {
- val imeVisibleRegion = it.visibleRegion(ComponentMatcher.IME)
+ val imeVisibleRegion = it.visibleRegion(ComponentNameMatcher.IME)
val appVisibleRegion = it.visibleRegion(imeTestApp)
if (imeVisibleRegion.region.isNotEmpty) {
- it.isVisible(ComponentMatcher.IME)
+ it.isVisible(ComponentNameMatcher.IME)
imeVisibleRegion.coversAtMost(appVisibleRegion.region)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 2207fe571e9f..2e22e6224813 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -29,7 +29,7 @@ import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -84,11 +84,11 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
// depends on how much of the animation transactions are sent to SF at once
// sometimes this layer appears for 2-3 frames, sometimes for only 1
- val recentTaskComponent = ComponentMatcher("", "RecentTaskScreenshotSurface")
+ val recentTaskComponent = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
- listOf(ComponentMatcher.SPLASH_SCREEN,
- ComponentMatcher.SNAPSHOT, recentTaskComponent)
+ listOf(ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT, recentTaskComponent)
)
}
}
@@ -97,11 +97,11 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
- val component = ComponentMatcher("", "RecentTaskScreenshotSurface")
+ val component = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry(
- ignoreWindows = listOf(ComponentMatcher.SPLASH_SCREEN,
- ComponentMatcher.SNAPSHOT,
+ ignoreWindows = listOf(ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT,
component)
)
}
@@ -111,9 +111,9 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Test
fun launcherWindowBecomesInvisible() {
testSpec.assertWm {
- this.isAppWindowVisible(ComponentMatcher.LAUNCHER)
+ this.isAppWindowVisible(ComponentNameMatcher.LAUNCHER)
.then()
- .isAppWindowInvisible(ComponentMatcher.LAUNCHER)
+ .isAppWindowInvisible(ComponentNameMatcher.LAUNCHER)
}
}
@@ -157,11 +157,11 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
fun imeLayerIsBecomesVisibleLegacy() {
Assume.assumeFalse(isShellTransitionsEnabled)
testSpec.assertLayers {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
.then()
- .isInvisible(ComponentMatcher.IME)
+ .isInvisible(ComponentNameMatcher.IME)
.then()
- .isVisible(ComponentMatcher.IME)
+ .isVisible(ComponentNameMatcher.IME)
}
}
@@ -170,7 +170,7 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
fun imeLayerBecomesVisibleShellTransit() {
Assume.assumeTrue(isShellTransitionsEnabled)
testSpec.assertLayers {
- this.isVisible(ComponentMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME)
}
}
@@ -178,9 +178,9 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Test
fun appLayerReplacesLauncher() {
testSpec.assertLayers {
- this.isVisible(ComponentMatcher.LAUNCHER)
+ this.isVisible(ComponentNameMatcher.LAUNCHER)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isVisible(testApp)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
index be7b80e8db82..4f47ec439da8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
@@ -31,7 +31,7 @@ import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -177,20 +177,20 @@ open class SwitchImeWindowsFromGestureNavTest(
@Test
open fun imeLayerIsVisibleWhenSwitchingToImeApp() {
testSpec.assertLayersStart {
- isVisible(ComponentMatcher.IME)
+ isVisible(ComponentNameMatcher.IME)
}
testSpec.assertLayersTag(TAG_IME_VISIBLE) {
- isVisible(ComponentMatcher.IME)
+ isVisible(ComponentNameMatcher.IME)
}
testSpec.assertLayersEnd {
- isVisible(ComponentMatcher.IME)
+ isVisible(ComponentNameMatcher.IME)
}
}
@Test
fun imeLayerIsInvisibleWhenSwitchingToTestApp() {
testSpec.assertLayersTag(TAG_IME_INVISIBLE) {
- isInvisible(ComponentMatcher.IME)
+ isInvisible(ComponentNameMatcher.IME)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
index a8c0a0b55009..5ac1712adbf2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
@@ -24,7 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarWindowIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 86b8e5fa1647..33c280ea78bb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import org.junit.FixMethodOrder
import org.junit.Test
@@ -118,7 +118,7 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Test
fun launcherWindowNotOnTop() {
testSpec.assertWm {
- this.isAppWindowNotOnTop(ComponentMatcher.LAUNCHER)
+ this.isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER)
}
}
@@ -128,7 +128,7 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Presubmit
@Test
fun launcherLayerNotVisible() {
- testSpec.assertLayers { this.isInvisible(ComponentMatcher.LAUNCHER) }
+ testSpec.assertLayers { this.isInvisible(ComponentNameMatcher.LAUNCHER) }
}
companion object {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index 2d4d7986a67e..bece406d5a96 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.replacesLayer
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Test
/**
@@ -46,7 +46,7 @@ abstract class OpenAppFromLauncherTransition(
*/
open fun appLayerReplacesLauncher() {
testSpec.replacesLayer(
- ComponentMatcher.LAUNCHER, testApp,
+ ComponentNameMatcher.LAUNCHER, testApp,
ignoreEntriesWithRotationLayer = true, ignoreSnapshot = true,
ignoreSplashscreen = true
)
@@ -61,12 +61,12 @@ abstract class OpenAppFromLauncherTransition(
@Test
open fun appWindowReplacesLauncherAsTopWindow() {
testSpec.assertWm {
- this.isAppWindowOnTop(ComponentMatcher.LAUNCHER)
+ this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
.then()
.isAppWindowOnTop(
testApp
- .or(ComponentMatcher.SNAPSHOT)
- .or(ComponentMatcher.SPLASH_SCREEN)
+ .or(ComponentNameMatcher.SNAPSHOT)
+ .or(ComponentNameMatcher.SPLASH_SCREEN)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index 220e4caf5faa..bfc7b39f9d9f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -26,7 +26,6 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index 9ed1bde86647..e517c2ad2c49 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
@@ -86,9 +86,9 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
testSpec.assertWm {
this.hasNoVisibleAppWindow()
.then()
- .isAppWindowOnTop(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
- .isAppWindowOnTop(ComponentMatcher.SPLASH_SCREEN, isOptional = true)
+ .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
.then()
.isAppWindowOnTop(testApp)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index 29730591c957..75311eaf5c66 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -26,7 +26,7 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -88,7 +88,7 @@ class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParamet
testSpec.assertWm {
this.hasNoVisibleAppWindow()
.then()
- .isAppWindowOnTop(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isAppWindowOnTop(showWhenLockedApp)
}
@@ -100,7 +100,7 @@ class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParamet
testSpec.assertLayers {
this.isInvisible(showWhenLockedApp)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isVisible(showWhenLockedApp)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index 1d8b0a64c70f..ecc60b8d45c0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -22,7 +22,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.Ignore
import org.junit.Test
@@ -77,9 +77,9 @@ abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
testSpec.assertWm {
this.hasNoVisibleAppWindow()
.then()
- .isAppWindowOnTop(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
- .isAppWindowOnTop(ComponentMatcher.SPLASH_SCREEN, isOptional = true)
+ .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
.then()
.isAppWindowOnTop(testApp)
}
@@ -152,7 +152,7 @@ abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
@Test
fun statusBarLayerIsVisibleAtEnd() {
testSpec.assertLayersEnd {
- this.isVisible(ComponentMatcher.STATUS_BAR)
+ this.isVisible(ComponentNameMatcher.STATUS_BAR)
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index 866e819bf5fc..78baddff582c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -34,7 +34,6 @@ import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
-import com.android.server.wm.traces.common.ComponentMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index 647607794fa9..53be7d43cce8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -29,7 +29,7 @@ import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
@@ -76,9 +76,9 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
fun navBarLayerVisibilityChanges() {
Assume.assumeFalse(testSpec.isTablet)
testSpec.assertLayers {
- this.isInvisible(ComponentMatcher.NAV_BAR)
+ this.isInvisible(ComponentNameMatcher.NAV_BAR)
.then()
- .isVisible(ComponentMatcher.NAV_BAR)
+ .isVisible(ComponentNameMatcher.NAV_BAR)
}
}
@@ -102,9 +102,9 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
fun navBarWindowsVisibilityChanges() {
Assume.assumeFalse(testSpec.isTablet)
testSpec.assertWm {
- this.isNonAppWindowInvisible(ComponentMatcher.NAV_BAR)
+ this.isNonAppWindowInvisible(ComponentNameMatcher.NAV_BAR)
.then()
- .isAboveAppWindowVisible(ComponentMatcher.NAV_BAR)
+ .isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
}
}
@@ -117,7 +117,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
fun taskBarLayerIsVisibleAtEnd() {
Assume.assumeTrue(testSpec.isTablet)
testSpec.assertLayersEnd {
- this.isVisible(ComponentMatcher.TASK_BAR)
+ this.isVisible(ComponentNameMatcher.TASK_BAR)
}
}
@@ -130,7 +130,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() {
testSpec.assertLayersEnd {
- this.isVisible(ComponentMatcher.STATUS_BAR)
+ this.isVisible(ComponentNameMatcher.STATUS_BAR)
}
}
@@ -180,7 +180,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
fun navBarLayerIsVisibleAtEnd() {
Assume.assumeFalse(testSpec.isTablet)
testSpec.assertLayersEnd {
- this.isVisible(ComponentMatcher.NAV_BAR)
+ this.isVisible(ComponentNameMatcher.NAV_BAR)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index 5d2b56707de9..8658c03acf60 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -24,7 +24,7 @@ import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Test
/**
@@ -65,9 +65,9 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
.then()
.isInvisible(testApp, isOptional = true)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
- .isVisible(ComponentMatcher.SPLASH_SCREEN, isOptional = true)
+ .isVisible(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
.then()
.isVisible(testApp)
}
@@ -77,9 +77,9 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
testSpec.assertLayers {
this.isInvisible(testApp)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
- .isVisible(ComponentMatcher.SPLASH_SCREEN, isOptional = true)
+ .isVisible(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
.then()
.isVisible(testApp)
}
@@ -110,9 +110,9 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
testSpec.assertWm {
this.isAppWindowInvisible(testApp)
.then()
- .isAppWindowVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
- .isAppWindowVisible(ComponentMatcher.SPLASH_SCREEN, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
.then()
.isAppWindowVisible(testApp)
}
@@ -130,8 +130,8 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
.then()
.isAppWindowOnTop(
testApp
- .or(ComponentMatcher.SNAPSHOT)
- .or(ComponentMatcher.SPLASH_SCREEN)
+ .or(ComponentNameMatcher.SNAPSHOT)
+ .or(ComponentNameMatcher.SPLASH_SCREEN)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index b482e5f3c3fb..fe5e74b87f93 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -30,9 +30,9 @@ import com.android.server.wm.flicker.helpers.NewTasksAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.testapp.ActivityOptions.LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME
import com.android.server.wm.flicker.testapp.ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
-import com.android.server.wm.traces.common.ComponentMatcher
-import com.android.server.wm.traces.common.ComponentMatcher.Companion.SPLASH_SCREEN
-import com.android.server.wm.traces.common.ComponentMatcher.Companion.WALLPAPER_BBQ_WRAPPER
+import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.SPLASH_SCREEN
+import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
import com.android.server.wm.traces.common.IComponentMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import org.junit.FixMethodOrder
@@ -117,7 +117,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
@Test
fun launcherWindowIsNeverVisible() {
testSpec.assertWm {
- this.isAppWindowInvisible(ComponentMatcher.LAUNCHER)
+ this.isAppWindowInvisible(ComponentNameMatcher.LAUNCHER)
}
}
@@ -130,7 +130,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
@Test
fun launcherLayerIsNeverVisible() {
testSpec.assertLayers {
- this.isInvisible(ComponentMatcher.LAUNCHER)
+ this.isInvisible(ComponentNameMatcher.LAUNCHER)
}
}
@@ -140,7 +140,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
@Postsubmit
@Test
fun colorLayerIsVisibleDuringTransition() {
- val bgColorLayer = ComponentMatcher("", "colorBackgroundLayer")
+ val bgColorLayer = ComponentNameMatcher("", "colorBackgroundLayer")
val displayBounds = WindowUtils.getDisplayBounds(testSpec.startRotation)
testSpec.assertLayers {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index a9fb0f261465..181767b3448d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -30,7 +30,7 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.Rect
import org.junit.Assume
import org.junit.Before
@@ -178,7 +178,7 @@ open class QuickSwitchBetweenTwoAppsBackTest(
testSpec.assertWm {
this.isAppWindowInvisible(testApp1)
.then()
- .isAppWindowVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isAppWindowVisible(testApp1)
}
@@ -238,9 +238,9 @@ open class QuickSwitchBetweenTwoAppsBackTest(
this.isAppWindowVisible(testApp2)
.then()
// TODO: Do we actually want to test this? Seems too implementation specific...
- .isAppWindowVisible(ComponentMatcher.LAUNCHER, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
.then()
- .isAppWindowVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isAppWindowVisible(testApp1)
}
@@ -257,9 +257,9 @@ open class QuickSwitchBetweenTwoAppsBackTest(
testSpec.assertLayers {
this.isVisible(testApp2)
.then()
- .isVisible(ComponentMatcher.LAUNCHER, isOptional = true)
+ .isVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isVisible(testApp1)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
index 2607ee5bb0ef..461bae482299 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
@@ -24,7 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarWindowIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 3b602126399d..0f05622c81bc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -31,7 +31,7 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.Rect
import org.junit.Assume
import org.junit.Before
@@ -112,7 +112,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Test
open fun startsWithApp1WindowsCoverFullScreen() {
testSpec.assertWmStart {
- this.visibleRegion(testApp1.or(ComponentMatcher.LETTERBOX))
+ this.visibleRegion(testApp1.or(ComponentNameMatcher.LETTERBOX))
.coversExactly(startDisplayBounds)
}
}
@@ -160,7 +160,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Test
open fun endsWithApp2LayersCoveringFullScreen() {
testSpec.assertLayersEnd {
- this.visibleRegion(testApp2.or(ComponentMatcher.LETTERBOX))
+ this.visibleRegion(testApp2.or(ComponentNameMatcher.LETTERBOX))
.coversExactly(startDisplayBounds)
}
}
@@ -187,7 +187,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
testSpec.assertWm {
this.isAppWindowInvisible(testApp2)
.then()
- .isAppWindowVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isAppWindowVisible(testApp2)
}
@@ -246,9 +246,9 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
testSpec.assertWm {
this.isAppWindowVisible(testApp1)
.then()
- .isAppWindowVisible(ComponentMatcher.LAUNCHER, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
.then()
- .isAppWindowVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isAppWindowVisible(testApp2)
}
@@ -265,9 +265,9 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
testSpec.assertLayers {
this.isVisible(testApp1)
.then()
- .isVisible(ComponentMatcher.LAUNCHER, isOptional = true)
+ .isVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isVisible(testApp2)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
index 27ae12566e94..f644b97e03df 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
@@ -24,7 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarWindowIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index c79b55251c74..d1f356c830eb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -30,7 +30,7 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.navBarWindowIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.Rect
import org.junit.Assume
import org.junit.FixMethodOrder
@@ -152,7 +152,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun startsWithLauncherWindowsCoverFullScreen() {
testSpec.assertWmStart {
- this.visibleRegion(ComponentMatcher.LAUNCHER).coversExactly(startDisplayBounds)
+ this.visibleRegion(ComponentNameMatcher.LAUNCHER).coversExactly(startDisplayBounds)
}
}
@@ -164,7 +164,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun startsWithLauncherLayersCoverFullScreen() {
testSpec.assertLayersStart {
- this.visibleRegion(ComponentMatcher.LAUNCHER).coversExactly(startDisplayBounds)
+ this.visibleRegion(ComponentNameMatcher.LAUNCHER).coversExactly(startDisplayBounds)
}
}
@@ -175,7 +175,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun startsWithLauncherBeingOnTop() {
testSpec.assertWmStart {
- this.isAppWindowOnTop(ComponentMatcher.LAUNCHER)
+ this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
}
}
@@ -228,9 +228,9 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun launcherWindowBecomesAndStaysInvisible() {
testSpec.assertWm {
- this.isAppWindowOnTop(ComponentMatcher.LAUNCHER)
+ this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
.then()
- .isAppWindowNotOnTop(ComponentMatcher.LAUNCHER)
+ .isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER)
}
}
@@ -243,9 +243,9 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun launcherLayerBecomesAndStaysInvisible() {
testSpec.assertLayers {
- this.isVisible(ComponentMatcher.LAUNCHER)
+ this.isVisible(ComponentNameMatcher.LAUNCHER)
.then()
- .isInvisible(ComponentMatcher.LAUNCHER)
+ .isInvisible(ComponentNameMatcher.LAUNCHER)
}
}
@@ -258,9 +258,9 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun appWindowIsVisibleOnceLauncherWindowIsInvisible() {
testSpec.assertWm {
- this.isAppWindowOnTop(ComponentMatcher.LAUNCHER)
+ this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
.then()
- .isAppWindowVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isAppWindowVisible(testApp)
}
@@ -275,9 +275,9 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun appLayerIsVisibleOnceLauncherLayerIsInvisible() {
testSpec.assertLayers {
- this.isVisible(ComponentMatcher.LAUNCHER)
+ this.isVisible(ComponentNameMatcher.LAUNCHER)
.then()
- .isVisible(ComponentMatcher.SNAPSHOT, isOptional = true)
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
.then()
.isVisible(testApp)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 5e80fabcd8a4..4be8963bf7b7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -25,7 +25,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -106,10 +106,10 @@ class ChangeAppRotationTest(
testSpec.assertLayers {
this.isVisible(testApp)
.then()
- .isVisible(ComponentMatcher.ROTATION)
+ .isVisible(ComponentNameMatcher.ROTATION)
.then()
.isVisible(testApp)
- .isInvisible(ComponentMatcher.ROTATION)
+ .isInvisible(ComponentNameMatcher.ROTATION)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 36a152117dcc..7e159d465b13 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -22,7 +22,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Test
/**
@@ -55,9 +55,9 @@ abstract class RotationTransition(testSpec: FlickerTestParameter) : BaseTest(tes
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
ignoreLayers = listOf(
- ComponentMatcher.SPLASH_SCREEN,
- ComponentMatcher.SNAPSHOT,
- ComponentMatcher("", "SecondaryHomeHandle")
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT,
+ ComponentNameMatcher("", "SecondaryHomeHandle")
)
)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 1e3caa43a07c..0912812afef9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -27,7 +27,7 @@ import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentMatcher
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
@@ -186,7 +186,7 @@ open class SeamlessAppRotationTest(
@Test
fun statusBarWindowIsAlwaysInvisible() {
testSpec.assertWm {
- this.isAboveAppWindowInvisible(ComponentMatcher.STATUS_BAR)
+ this.isAboveAppWindowInvisible(ComponentNameMatcher.STATUS_BAR)
}
}
@@ -198,7 +198,7 @@ open class SeamlessAppRotationTest(
@Test
fun statusBarLayerIsAlwaysInvisible() {
testSpec.assertLayers {
- this.isInvisible(ComponentMatcher.STATUS_BAR)
+ this.isInvisible(ComponentNameMatcher.STATUS_BAR)
}
}
diff --git a/tools/lint/Android.bp b/tools/lint/Android.bp
index 260104145505..96618f413db1 100644
--- a/tools/lint/Android.bp
+++ b/tools/lint/Android.bp
@@ -51,3 +51,9 @@ java_test_host {
unit_test: true,
},
}
+
+python_binary_host {
+ name: "lint_fix",
+ main: "fix/lint_fix.py",
+ srcs: ["fix/lint_fix.py"],
+}
diff --git a/tools/lint/README.md b/tools/lint/README.md
index c674d36431b7..99149c140c1c 100644
--- a/tools/lint/README.md
+++ b/tools/lint/README.md
@@ -44,6 +44,10 @@ m out/soong/.intermediates/frameworks/base/services/autofill/services.autofill/a
environment variable with the id of the lint. For example:
`ANDROID_LINT_CHECK=UnusedTokenOfOriginalCallingIdentity m out/[...]/lint-report.html`
+## How to apply automatic fixes suggested by lint
+
+See [lint_fix](fix/README.md)
+
## Create or update a baseline
Baseline files can be used to silence known errors (and warnings) that are deemed to be safe. When
diff --git a/tools/lint/fix/README.md b/tools/lint/fix/README.md
new file mode 100644
index 000000000000..367d0bcb1aa7
--- /dev/null
+++ b/tools/lint/fix/README.md
@@ -0,0 +1,46 @@
+# Refactoring the platform with lint
+Inspiration: go/refactor-the-platform-with-lint\
+**Special Thanks: brufino@, azharaa@, for the prior work that made this all possible**
+
+## What is this?
+
+It's a python script that runs the framework linter,
+and then copies modified files back into the source tree.\
+Why python, you ask? Because python is cool ¯\_(ツ)_/¯.
+
+## Why?
+
+Lint is not allowed to modify source files directly via lint's `--apply-suggestions` flag.
+As a compromise, soong zips up the (potentially) modified sources and leaves them in an intermediate
+directory. This script runs the lint, unpacks those files, and copies them back into the tree.
+
+## How do I run it?
+**WARNING: You probably want to commit/stash any changes to your working tree before doing this...**
+
+From this directory, run `python lint_fix.py -h`.
+The script's help output explains things that are omitted here.
+
+Alternatively, there is a python binary target you can build to make this
+available anywhere in your tree:
+```
+m lint_fix
+lint_fix -h
+```
+
+**Gotcha**: You must have run `source build/envsetup.sh` and `lunch` first.
+
+Example: `lint_fix frameworks/base/services/core/services.core.unboosted UseEnforcePermissionAnnotation --dry-run`
+```shell
+(
+export ANDROID_LINT_CHECK=UseEnforcePermissionAnnotation;
+cd $ANDROID_BUILD_TOP;
+source build/envsetup.sh;
+rm out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/lint/lint-report.html;
+m out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/lint/lint-report.html;
+cd out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/lint;
+unzip suggested-fixes.zip -d suggested-fixes;
+cd suggested-fixes;
+find . -path ./out -prune -o -name '*.java' -print | xargs -n 1 sh -c 'cp $1 $ANDROID_BUILD_TOP/$1' --;
+rm -rf suggested-fixes
+)
+```
diff --git a/tools/lint/fix/lint_fix.py b/tools/lint/fix/lint_fix.py
new file mode 100644
index 000000000000..3ff8131489ff
--- /dev/null
+++ b/tools/lint/fix/lint_fix.py
@@ -0,0 +1,76 @@
+import argparse
+import os
+import sys
+
+ANDROID_BUILD_TOP = os.environ.get("ANDROID_BUILD_TOP")
+PATH_PREFIX = "out/soong/.intermediates"
+PATH_SUFFIX = "android_common/lint"
+FIX_DIR = "suggested-fixes"
+
+parser = argparse.ArgumentParser(description="""
+This is a python script that applies lint fixes to the platform:
+1. Set up the environment, etc.
+2. Build the lint and run it.
+3. Unpack soong's intermediate zip containing source files modified by lint.
+4. Copy the modified files back into the tree.
+
+**Gotcha**: You must have run `source build/envsetup.sh` and `lunch` \
+so that the `ANDROID_BUILD_TOP` environment variable has been set.
+Alternatively, set it manually in your shell.
+""", formatter_class=argparse.RawTextHelpFormatter)
+
+parser.add_argument('build_path', metavar='build_path', type=str,
+ help='The build module to run '
+ '(e.g. frameworks/base/framework-minus-apex or '
+ 'frameworks/base/services/core/services.core.unboosted)')
+
+parser.add_argument('--check', metavar='check', type=str,
+ help='Which lint to run. Passed to the ANDROID_LINT_CHECK environment variable.')
+
+parser.add_argument('--dry-run', dest='dry_run', action='store_true',
+ help='Just print the resulting shell script instead of running it.')
+
+parser.add_argument('--no-fix', dest='no_fix', action='store_true',
+ help='Just build and run the lint, do NOT apply the fixes.')
+
+args = parser.parse_args()
+
+path = f"{PATH_PREFIX}/{args.build_path}/{PATH_SUFFIX}"
+target = f"{path}/lint-report.html"
+
+commands = []
+
+if not args.dry_run:
+ commands += [f"export ANDROID_BUILD_TOP={ANDROID_BUILD_TOP}"]
+
+if args.check:
+ commands += [f"export ANDROID_LINT_CHECK={args.check}"]
+
+commands += [
+ "cd $ANDROID_BUILD_TOP",
+ "source build/envsetup.sh",
+ f"rm {target}", # remove the file first so soong doesn't think there is no work to do
+ f"m {target}",
+]
+
+if not args.no_fix:
+ commands += [
+ f"cd {path}",
+ f"unzip {FIX_DIR}.zip -d {FIX_DIR}",
+ f"cd {FIX_DIR}",
+ # Find all the java files in the fix directory, excluding the ./out subdirectory,
+ # and copy them back into the same path within the tree.
+ f"find . -path ./out -prune -o -name '*.java' -print | xargs -n 1 sh -c 'cp $1 $ANDROID_BUILD_TOP/$1' --",
+ f"rm -rf {FIX_DIR}"
+ ]
+
+if args.dry_run:
+ print("(\n" + ";\n".join(commands) + "\n)")
+ sys.exit(0)
+
+with_echo = []
+for c in commands:
+ with_echo.append(f'echo "{c}"')
+ with_echo.append(c)
+
+os.system("(\n" + ";\n".join(with_echo) + "\n)")