summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp7
-rw-r--r--apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java14
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Agent.java38
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java44
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Ledger.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Scribe.java24
-rw-r--r--core/api/current.txt8
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java21
-rw-r--r--core/java/android/app/UiAutomationConnection.java1
-rw-r--r--core/java/android/os/BatteryStats.java7
-rw-r--r--core/java/android/util/FeatureFlagUtils.java9
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java77
-rw-r--r--core/java/android/view/InputDevice.java26
-rw-r--r--core/java/android/view/View.java138
-rw-r--r--core/java/android/view/ViewGroup.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java1
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java57
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java35
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java25
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java24
-rw-r--r--core/java/android/view/accessibility/DirectAccessibilityConnection.java4
-rw-r--r--core/java/android/view/textservice/TextServicesManager.java4
-rw-r--r--core/java/android/widget/TextView.java7
-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.bp5
-rw-r--r--core/jni/android_view_InputDevice.cpp8
-rw-r--r--core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java5
-rw-r--r--core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java4
-rw-r--r--media/Android.bp73
-rw-r--r--media/aidl/android/media/audio/common/AudioAttributes.aidl59
-rw-r--r--media/aidl/android/media/audio/common/AudioFlag.aidl116
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioAttributes.aidl42
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFlag.aidl54
-rw-r--r--media/java/android/media/AudioManager.java4
-rw-r--r--media/java/android/media/SoundPool.java4
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java13
-rw-r--r--media/jni/Android.bp2
-rw-r--r--media/jni/android_media_tv_Tuner.cpp64
-rw-r--r--media/jni/android_media_tv_Tuner.h3
-rw-r--r--media/jni/soundpool/SoundPool.cpp5
-rw-r--r--media/jni/soundpool/SoundPool.h2
-rw-r--r--media/jni/soundpool/Stream.cpp15
-rw-r--r--media/jni/soundpool/Stream.h5
-rw-r--r--media/jni/soundpool/StreamManager.cpp11
-rw-r--r--media/jni/soundpool/StreamManager.h2
-rw-r--r--media/jni/soundpool/android_media_SoundPool.cpp13
-rw-r--r--media/jni/tuner/TunerClient.cpp7
-rw-r--r--media/jni/tuner/TunerClient.h7
-rw-r--r--packages/SettingsLib/Spa/gallery/AndroidManifest.xml2
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt32
-rw-r--r--packages/SystemUI/TEST_MAPPING11
-rw-r--r--packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json1
-rw-r--r--packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardViewMediatorLogger.kt690
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java196
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java312
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardViewMediatorLog.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt12
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java25
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java1
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java8
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java80
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java15
-rw-r--r--services/core/java/com/android/server/app/GameManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java4
-rw-r--r--services/core/java/com/android/server/pm/ReconcilePackageUtils.java47
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/parsing/PackageCacher.java9
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java76
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java11
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java10
-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/powerstats/PowerStatsDataStorage.java33
-rw-r--r--services/core/java/com/android/server/powerstats/PowerStatsLogger.java16
-rw-r--r--services/core/java/com/android/server/textservices/TextServicesManagerService.java52
-rw-r--r--services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java10
-rw-r--r--services/core/java/com/android/server/vibrator/AbstractVibratorStep.java92
-rw-r--r--services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java24
-rw-r--r--services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java18
-rw-r--r--services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java15
-rw-r--r--services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java21
-rw-r--r--services/core/java/com/android/server/vibrator/RampOffVibratorStep.java12
-rw-r--r--services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java68
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationStepConductor.java13
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java19
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java30
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java7
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java5
-rw-r--r--services/core/java/com/android/server/wm/Transition.java37
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java11
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java28
-rw-r--r--services/proguard.flags3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java49
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt6
-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--services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java43
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java207
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java4
-rw-r--r--tests/Input/src/com/android/test/input/InputDeviceTest.java14
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java10
-rw-r--r--tests/testables/src/android/testing/TestableLooper.java44
-rw-r--r--tests/testables/tests/AndroidManifest.xml2
-rw-r--r--tests/testables/tests/AndroidTest.xml27
-rw-r--r--tests/testables/tests/src/android/testing/TestableLooperTest.java65
132 files changed, 4510 insertions, 2491 deletions
diff --git a/Android.bp b/Android.bp
index 30b38d302a2d..c0a70b99827e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -255,7 +255,10 @@ filegroup {
java_defaults {
name: "framework-minus-apex-defaults",
- defaults: ["framework-aidl-export-defaults"],
+ defaults: [
+ "framework-aidl-export-defaults",
+ "latest_android_hardware_soundtrigger3_java_static",
+ ],
srcs: [
":framework-non-updatable-sources",
"core/java/**/*.logtags",
@@ -365,8 +368,6 @@ java_defaults {
sdk_version: "core_platform",
static_libs: [
"android.hardware.common.fmq-V1-java",
- // TODO(b/184162091)
- "android.hardware.soundtrigger3-V1-java",
"bouncycastle-repackaged-unbundled",
"framework-internal-utils",
// If MimeMap ever becomes its own APEX, then this dependency would need to be removed
diff --git a/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java b/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
index 81685cbbd594..33b2bea1da66 100644
--- a/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
+++ b/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
@@ -37,6 +37,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.adservices.service.js.IsolateSettings;
import com.android.adservices.service.js.JSScriptArgument;
import com.android.adservices.service.js.JSScriptArrayArgument;
import com.android.adservices.service.js.JSScriptEngine;
@@ -314,7 +315,11 @@ public class JSScriptEnginePerfTests {
@NonNull CountDownLatch resultLatch) {
Objects.requireNonNull(engine);
Objects.requireNonNull(resultLatch);
- ListenableFuture<String> result = engine.evaluate(jsScript, args, functionName);
+ ListenableFuture<String> result = engine.evaluate(
+ jsScript,
+ args,
+ functionName,
+ IsolateSettings.forMaxHeapSizeEnforcementDisabled());
result.addListener(resultLatch::countDown, sExecutorService);
return result;
}
@@ -328,7 +333,12 @@ public class JSScriptEnginePerfTests {
@NonNull CountDownLatch resultLatch) {
Objects.requireNonNull(engine);
Objects.requireNonNull(resultLatch);
- ListenableFuture<String> result = engine.evaluate(jsScript, wasmScript, args, functionName);
+ ListenableFuture<String> result = engine.evaluate(
+ jsScript,
+ wasmScript,
+ args,
+ functionName,
+ IsolateSettings.forMaxHeapSizeEnforcementDisabled());
result.addListener(resultLatch::countDown, sExecutorService);
return result;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index d4a1cd234c39..4fe021a35f98 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -721,25 +721,28 @@ class Agent {
@GuardedBy("mLock")
void distributeBasicIncomeLocked(int batteryLevel) {
- final List<InstalledPackageInfo> pkgs = mIrs.getInstalledPackages();
+ final SparseArrayMap<String, InstalledPackageInfo> pkgs = mIrs.getInstalledPackages();
final long now = getCurrentTimeMillis();
- for (int i = 0; i < pkgs.size(); ++i) {
- final InstalledPackageInfo pkgInfo = pkgs.get(i);
- if (!shouldGiveCredits(pkgInfo)) {
- continue;
- }
- final int userId = UserHandle.getUserId(pkgInfo.uid);
- final String pkgName = pkgInfo.packageName;
- final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
- final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
- final double perc = batteryLevel / 100d;
- // TODO: maybe don't give credits to bankrupt apps until battery level >= 50%
- final long shortfall = minBalance - ledger.getCurrentBalance();
- if (shortfall > 0) {
- recordTransactionLocked(userId, pkgName, ledger,
- new Ledger.Transaction(now, now, REGULATION_BASIC_INCOME,
- null, (long) (perc * shortfall), 0), true);
+ for (int uIdx = pkgs.numMaps() - 1; uIdx >= 0; --uIdx) {
+ final int userId = pkgs.keyAt(uIdx);
+
+ for (int pIdx = pkgs.numElementsForKeyAt(uIdx) - 1; pIdx >= 0; --pIdx) {
+ final InstalledPackageInfo pkgInfo = pkgs.valueAt(uIdx, pIdx);
+ if (!shouldGiveCredits(pkgInfo)) {
+ continue;
+ }
+ final String pkgName = pkgInfo.packageName;
+ final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
+ final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
+ final double perc = batteryLevel / 100d;
+ // TODO: maybe don't give credits to bankrupt apps until battery level >= 50%
+ final long shortfall = minBalance - ledger.getCurrentBalance();
+ if (shortfall > 0) {
+ recordTransactionLocked(userId, pkgName, ledger,
+ new Ledger.Transaction(now, now, REGULATION_BASIC_INCOME,
+ null, (long) (perc * shortfall), 0), true);
+ }
}
}
}
@@ -1325,7 +1328,6 @@ class Agent {
@GuardedBy("mLock")
void dumpLocked(IndentingPrintWriter pw) {
- pw.println();
mBalanceThresholdAlarmQueue.dump(pw);
pw.println();
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
index 2fb0c1a36e07..22a2f5163538 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
@@ -405,6 +405,10 @@ public abstract class EconomicPolicy {
return "PROMOTION";
case REGULATION_DEMOTION:
return "DEMOTION";
+ case REGULATION_BG_RESTRICTED:
+ return "BG_RESTRICTED";
+ case REGULATION_BG_UNRESTRICTED:
+ return "BG_UNRESTRICTED";
}
return "UNKNOWN_REGULATION:" + Integer.toHexString(eventId);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 2b8272208c3e..448a808ff52f 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -136,7 +136,7 @@ public class InternalResourceService extends SystemService {
@NonNull
@GuardedBy("mLock")
- private final List<InstalledPackageInfo> mPkgCache = new ArrayList<>();
+ private final SparseArrayMap<String, InstalledPackageInfo> mPkgCache = new SparseArrayMap<>();
/** Cached mapping of UIDs (for all users) to a list of packages in the UID. */
@GuardedBy("mLock")
@@ -343,7 +343,7 @@ public class InternalResourceService extends SystemService {
}
@NonNull
- List<InstalledPackageInfo> getInstalledPackages() {
+ SparseArrayMap<String, InstalledPackageInfo> getInstalledPackages() {
synchronized (mLock) {
return mPkgCache;
}
@@ -354,11 +354,13 @@ public class InternalResourceService extends SystemService {
List<InstalledPackageInfo> getInstalledPackages(final int userId) {
final List<InstalledPackageInfo> userPkgs = new ArrayList<>();
synchronized (mLock) {
- for (int i = 0; i < mPkgCache.size(); ++i) {
- final InstalledPackageInfo packageInfo = mPkgCache.get(i);
- if (UserHandle.getUserId(packageInfo.uid) == userId) {
- userPkgs.add(packageInfo);
- }
+ final int uIdx = mPkgCache.indexOfKey(userId);
+ if (uIdx < 0) {
+ return userPkgs;
+ }
+ for (int p = mPkgCache.numElementsForKeyAt(uIdx) - 1; p >= 0; --p) {
+ final InstalledPackageInfo packageInfo = mPkgCache.valueAt(uIdx, p);
+ userPkgs.add(packageInfo);
}
}
return userPkgs;
@@ -511,7 +513,7 @@ public class InternalResourceService extends SystemService {
mPackageToUidCache.add(userId, pkgName, uid);
}
synchronized (mLock) {
- mPkgCache.add(new InstalledPackageInfo(packageInfo));
+ mPkgCache.add(userId, pkgName, new InstalledPackageInfo(packageInfo));
mUidToPackageCache.add(uid, pkgName);
// TODO: only do this when the user first launches the app (app leaves stopped state)
mAgent.grantBirthrightLocked(userId, pkgName);
@@ -532,14 +534,7 @@ public class InternalResourceService extends SystemService {
synchronized (mLock) {
mUidToPackageCache.remove(uid, pkgName);
mVipOverrides.delete(userId, pkgName);
- for (int i = 0; i < mPkgCache.size(); ++i) {
- final InstalledPackageInfo pkgInfo = mPkgCache.get(i);
- if (UserHandle.getUserId(pkgInfo.uid) == userId
- && pkgName.equals(pkgInfo.packageName)) {
- mPkgCache.remove(i);
- break;
- }
- }
+ mPkgCache.delete(userId, pkgName);
mAgent.onPackageRemovedLocked(userId, pkgName);
}
}
@@ -560,7 +555,8 @@ public class InternalResourceService extends SystemService {
final List<PackageInfo> pkgs =
mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId);
for (int i = pkgs.size() - 1; i >= 0; --i) {
- mPkgCache.add(new InstalledPackageInfo(pkgs.get(i)));
+ final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i));
+ mPkgCache.add(userId, ipo.packageName, ipo);
}
mAgent.grantBirthrightsLocked(userId);
}
@@ -570,15 +566,15 @@ public class InternalResourceService extends SystemService {
synchronized (mLock) {
mVipOverrides.delete(userId);
ArrayList<String> removedPkgs = new ArrayList<>();
- for (int i = mPkgCache.size() - 1; i >= 0; --i) {
- final InstalledPackageInfo pkgInfo = mPkgCache.get(i);
- if (UserHandle.getUserId(pkgInfo.uid) == userId) {
+ final int uIdx = mPkgCache.indexOfKey(userId);
+ if (uIdx >= 0) {
+ for (int p = mPkgCache.numElementsForKeyAt(uIdx) - 1; p >= 0; --p) {
+ final InstalledPackageInfo pkgInfo = mPkgCache.valueAt(uIdx, p);
removedPkgs.add(pkgInfo.packageName);
mUidToPackageCache.remove(pkgInfo.uid);
- mPkgCache.remove(i);
- break;
}
}
+ mPkgCache.delete(userId);
mAgent.onUserRemovedLocked(userId, removedPkgs);
}
}
@@ -727,7 +723,8 @@ public class InternalResourceService extends SystemService {
final List<PackageInfo> pkgs =
mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId);
for (int i = pkgs.size() - 1; i >= 0; --i) {
- mPkgCache.add(new InstalledPackageInfo(pkgs.get(i)));
+ final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i));
+ mPkgCache.add(userId, ipo.packageName, ipo);
}
}
}
@@ -1185,7 +1182,6 @@ public class InternalResourceService extends SystemService {
// User setting should override DeviceConfig setting.
// NOTE: There's currently no way for a user to reset the value (via UI), so if a user
// manually toggles TARE via UI, we'll always defer to the user's current setting
- // TODO: add a "reset" value if the user toggle is an issue
final boolean isTareEnabledDC = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TARE,
KEY_DC_ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE == 1);
final boolean isTareEnabled = Settings.Global.getInt(mContentResolver,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
index e91ed1287e1b..620d1a0da76f 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
@@ -247,7 +247,7 @@ class Ledger {
boolean printedTransactionTitle = false;
for (int t = 0; t < Math.min(MAX_TRANSACTION_COUNT, numRecentTransactions); ++t) {
- final int idx = (mTransactionIndex - t + MAX_TRANSACTION_COUNT) % MAX_TRANSACTION_COUNT;
+ final int idx = (mTransactionIndex + t) % MAX_TRANSACTION_COUNT;
final Transaction transaction = mTransactions[idx];
if (transaction == null) {
continue;
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
index 2cae83f4aad5..29478d05e066 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
@@ -216,17 +216,21 @@ public class Scribe {
mRemainingConsumableCakes = 0;
final SparseArray<ArraySet<String>> installedPackagesPerUser = new SparseArray<>();
- final List<InstalledPackageInfo> installedPackages = mIrs.getInstalledPackages();
- for (int i = 0; i < installedPackages.size(); ++i) {
- final InstalledPackageInfo packageInfo = installedPackages.get(i);
- if (packageInfo.uid != InstalledPackageInfo.NO_UID) {
- final int userId = UserHandle.getUserId(packageInfo.uid);
- ArraySet<String> pkgsForUser = installedPackagesPerUser.get(userId);
- if (pkgsForUser == null) {
- pkgsForUser = new ArraySet<>();
- installedPackagesPerUser.put(userId, pkgsForUser);
+ final SparseArrayMap<String, InstalledPackageInfo> installedPackages =
+ mIrs.getInstalledPackages();
+ for (int uIdx = installedPackages.numMaps() - 1; uIdx >= 0; --uIdx) {
+ final int userId = installedPackages.keyAt(uIdx);
+
+ for (int pIdx = installedPackages.numElementsForKeyAt(uIdx) - 1; pIdx >= 0; --pIdx) {
+ final InstalledPackageInfo packageInfo = installedPackages.valueAt(uIdx, pIdx);
+ if (packageInfo.uid != InstalledPackageInfo.NO_UID) {
+ ArraySet<String> pkgsForUser = installedPackagesPerUser.get(userId);
+ if (pkgsForUser == null) {
+ pkgsForUser = new ArraySet<>();
+ installedPackagesPerUser.put(userId, pkgsForUser);
+ }
+ pkgsForUser.add(packageInfo.packageName);
}
- pkgsForUser.add(packageInfo.packageName);
}
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 317f8eb5c6b5..eace67b79cd5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -49972,6 +49972,7 @@ package android.view {
method public void invalidate();
method public void invalidateDrawable(@NonNull android.graphics.drawable.Drawable);
method public void invalidateOutline();
+ method public boolean isAccessibilityDataPrivate();
method public boolean isAccessibilityFocused();
method public boolean isAccessibilityHeading();
method public boolean isActivated();
@@ -50149,6 +50150,7 @@ package android.view {
method public void scrollTo(int, int);
method public void sendAccessibilityEvent(int);
method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
+ method public void setAccessibilityDataPrivate(int);
method public void setAccessibilityDelegate(@Nullable android.view.View.AccessibilityDelegate);
method public void setAccessibilityHeading(boolean);
method public void setAccessibilityLiveRegion(int);
@@ -50329,6 +50331,9 @@ package android.view {
method @CallSuper protected boolean verifyDrawable(@NonNull android.graphics.drawable.Drawable);
method @Deprecated public boolean willNotCacheDrawing();
method public boolean willNotDraw();
+ field public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0; // 0x0
+ field public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 2; // 0x2
+ field public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 1; // 0x1
field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
@@ -51781,9 +51786,11 @@ package android.view.accessibility {
method public int getSpeechStateChangeTypes();
method public int getWindowChanges();
method public void initFromParcel(android.os.Parcel);
+ method public boolean isAccessibilityDataPrivate();
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(int);
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain();
+ method public void setAccessibilityDataPrivate(boolean);
method public void setAction(int);
method public void setContentChangeTypes(int);
method public void setEventTime(long);
@@ -51874,6 +51881,7 @@ package android.view.accessibility {
method public static boolean isAccessibilityButtonSupported();
method public boolean isAudioDescriptionRequested();
method public boolean isEnabled();
+ method public boolean isRequestFromAccessibilityTool();
method public boolean isTouchExplorationEnabled();
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
method public boolean removeAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f45298a630cd..4e594c1741fe 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -89,6 +89,7 @@ package android.accessibilityservice {
public class AccessibilityServiceInfo implements android.os.Parcelable {
method @NonNull public android.content.ComponentName getComponentName();
+ method public void setAccessibilityTool(boolean);
}
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 2e89ce83cd36..8f6bfd3b13db 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -784,6 +784,7 @@ public class AccessibilityServiceInfo implements Parcelable {
mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout;
mInteractiveUiTimeout = other.mInteractiveUiTimeout;
flags = other.flags;
+ mIsAccessibilityTool = other.mIsAccessibilityTool;
}
private boolean isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat) {
@@ -1112,6 +1113,26 @@ public class AccessibilityServiceInfo implements Parcelable {
}
/**
+ * Sets whether the service is used to assist users with disabilities.
+ *
+ * <p>
+ * This property is normally provided in the service's {@link #mResolveInfo ResolveInfo}.
+ * </p>
+ *
+ * <p>
+ * This method is helpful for unit testing. However, this property is not dynamically
+ * configurable by a standard {@link AccessibilityService} so it's not possible to update the
+ * copy held by the system with this method.
+ * </p>
+ *
+ * @hide
+ */
+ @TestApi
+ public void setAccessibilityTool(boolean isAccessibilityTool) {
+ mIsAccessibilityTool = isAccessibilityTool;
+ }
+
+ /**
* Indicates if the service is used to assist users with disabilities.
*
* @return {@code true} if the property is set to true.
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index a045157e02db..8d57e32a763c 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -550,6 +550,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS);
+ info.setAccessibilityTool(true);
try {
// Calling out with a lock held is fine since if the system
// process is gone the client calling in will be killed.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 09a52e452f9a..da206268917e 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2326,11 +2326,6 @@ 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();
@@ -7615,8 +7610,6 @@ 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/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 0338cebf75c6..bca100a1d81e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -52,13 +52,6 @@ public class FeatureFlagUtils {
public static final String SETTINGS_SUPPORT_LARGE_SCREEN = "settings_support_large_screen";
/**
- * Support per app's language selection
- * @hide
- */
- public static final String SETTINGS_APP_LANGUAGE_SELECTION = "settings_app_language_selection";
-
-
- /**
* Feature flag to allow/restrict intent redirection from/to clone profile.
* Default value is false,this is to ensure that framework is not impacted by intent redirection
* till we are ready to launch.
@@ -139,7 +132,6 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true");
DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true");
DEFAULT_FLAGS.put("settings_search_always_expand", "true");
- DEFAULT_FLAGS.put(SETTINGS_APP_LANGUAGE_SELECTION, "true");
DEFAULT_FLAGS.put(SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE, "false");
DEFAULT_FLAGS.put(SETTINGS_APP_LOCALE_OPT_IN_ENABLED, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true");
@@ -154,7 +146,6 @@ public class FeatureFlagUtils {
private static final Set<String> PERSISTENT_FLAGS;
static {
PERSISTENT_FLAGS = new HashSet<>();
- PERSISTENT_FLAGS.add(SETTINGS_APP_LANGUAGE_SELECTION);
PERSISTENT_FLAGS.add(SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE);
PERSISTENT_FLAGS.add(SETTINGS_APP_LOCALE_OPT_IN_ENABLED);
PERSISTENT_FLAGS.add(SETTINGS_SUPPORT_LARGE_SCREEN);
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index a6f63e859049..510bde1deb5d 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -89,9 +89,7 @@ public final class AccessibilityInteractionController {
// Callbacks should have the same configuration of the flags below to allow satisfying a pending
// node request on prefetch
- private static final int FLAGS_AFFECTING_REPORTED_DATA =
- AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
- | AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
+ private static final int FLAGS_AFFECTING_REPORTED_DATA = AccessibilityNodeInfo.FLAG_REPORT_MASK;
private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
new ArrayList<AccessibilityNodeInfo>();
@@ -167,6 +165,11 @@ public final class AccessibilityInteractionController {
return (view != null) && (view.getWindowVisibility() == View.VISIBLE && view.isShown());
}
+ private boolean isVisibleToAccessibilityService(View view) {
+ return view != null && (mA11yManager.isRequestFromAccessibilityTool()
+ || !view.isAccessibilityDataPrivate());
+ }
+
public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
long accessibilityNodeId, Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
@@ -358,7 +361,7 @@ public final class AccessibilityInteractionController {
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
return;
}
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ setAccessibilityFetchFlags(flags);
requestedView = findViewByAccessibilityId(accessibilityViewId);
if (requestedView != null && isShown(requestedView)) {
requestedNode = populateAccessibilityNodeInfoForView(
@@ -371,7 +374,7 @@ public final class AccessibilityInteractionController {
mPrefetcher.prefetchAccessibilityNodeInfos(requestedView,
requestedNode == null ? null : new AccessibilityNodeInfo(requestedNode),
infos);
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
}
}
} finally {
@@ -396,7 +399,7 @@ public final class AccessibilityInteractionController {
}
mPrefetcher.prefetchAccessibilityNodeInfos(requestedView,
requestedNode == null ? null : new AccessibilityNodeInfo(requestedNode), infos);
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
updateInfosForViewPort(infos, spec, matrixValues, interactiveRegion);
final SatisfiedFindAccessibilityNodeByAccessibilityIdRequest satisfiedRequest =
getSatisfiedRequestInPrefetch(requestedNode == null ? null : requestedNode, infos,
@@ -478,7 +481,7 @@ public final class AccessibilityInteractionController {
|| viewId == null) {
return;
}
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ setAccessibilityFetchFlags(flags);
final View root = findViewByAccessibilityId(accessibilityViewId);
if (root != null) {
final int resolvedViewId = root.getContext().getResources()
@@ -494,7 +497,7 @@ public final class AccessibilityInteractionController {
mAddNodeInfosForViewId.reset();
}
} finally {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
updateInfosForViewportAndReturnFindNodeResult(
infos, callback, interactionId, spec, matrixValues, interactiveRegion);
}
@@ -542,7 +545,7 @@ public final class AccessibilityInteractionController {
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
return;
}
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ setAccessibilityFetchFlags(flags);
final View root = findViewByAccessibilityId(accessibilityViewId);
if (root != null && isShown(root)) {
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
@@ -561,7 +564,7 @@ public final class AccessibilityInteractionController {
final int viewCount = foundViews.size();
for (int i = 0; i < viewCount; i++) {
View foundView = foundViews.get(i);
- if (isShown(foundView)) {
+ if (isShown(foundView) && isVisibleToAccessibilityService(foundView)) {
provider = foundView.getAccessibilityNodeProvider();
if (provider != null) {
List<AccessibilityNodeInfo> infosFromProvider =
@@ -579,7 +582,7 @@ public final class AccessibilityInteractionController {
}
}
} finally {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
updateInfosForViewportAndReturnFindNodeResult(
infos, callback, interactionId, spec, matrixValues, interactiveRegion);
}
@@ -627,7 +630,7 @@ public final class AccessibilityInteractionController {
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
return;
}
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ setAccessibilityFetchFlags(flags);
final View root = findViewByAccessibilityId(accessibilityViewId);
if (root != null && isShown(root)) {
switch (focusType) {
@@ -642,6 +645,9 @@ public final class AccessibilityInteractionController {
if (!isShown(host)) {
break;
}
+ if (!isVisibleToAccessibilityService(host)) {
+ break;
+ }
// If the host has a provider ask this provider to search for the
// focus instead fetching all provider nodes to do the search here.
AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
@@ -662,6 +668,9 @@ public final class AccessibilityInteractionController {
if (!isShown(target)) {
break;
}
+ if (!isVisibleToAccessibilityService(target)) {
+ break;
+ }
AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
if (provider != null) {
focused = provider.findFocus(focusType);
@@ -675,7 +684,7 @@ public final class AccessibilityInteractionController {
}
}
} finally {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
updateInfoForViewportAndReturnFindNodeResult(
focused, callback, interactionId, spec, matrixValues, interactiveRegion);
}
@@ -722,7 +731,7 @@ public final class AccessibilityInteractionController {
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
return;
}
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ setAccessibilityFetchFlags(flags);
final View root = findViewByAccessibilityId(accessibilityViewId);
if (root != null && isShown(root)) {
View nextView = root.focusSearch(direction);
@@ -731,7 +740,7 @@ public final class AccessibilityInteractionController {
}
}
} finally {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
updateInfoForViewportAndReturnFindNodeResult(
next, callback, interactionId, spec, matrixValues, interactiveRegion);
}
@@ -778,9 +787,9 @@ public final class AccessibilityInteractionController {
mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) {
return;
}
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ setAccessibilityFetchFlags(flags);
final View target = findViewByAccessibilityId(accessibilityViewId);
- if (target != null && isShown(target)) {
+ if (target != null && isShown(target) && isVisibleToAccessibilityService(target)) {
mA11yManager.notifyPerformingAction(action);
if (action == R.id.accessibilityActionClickOnClickableSpan) {
// Handle this hidden action separately
@@ -799,7 +808,7 @@ public final class AccessibilityInteractionController {
}
} finally {
try {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
callback.setPerformAccessibilityActionResult(succeeded, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -823,9 +832,9 @@ public final class AccessibilityInteractionController {
return;
}
try {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags =
- AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
- final View root = mViewRootImpl.mView;
+ setAccessibilityFetchFlags(
+ AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS);
+ final View root = getRootView();
if (root != null && isShown(root)) {
final View host = mViewRootImpl.mAccessibilityFocusedHost;
// If there is no accessibility focus host or it is not a descendant
@@ -849,7 +858,7 @@ public final class AccessibilityInteractionController {
}
}
} finally {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ resetAccessibilityFetchFlags();
}
}
@@ -869,7 +878,7 @@ public final class AccessibilityInteractionController {
|| mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) {
return;
}
- final View root = mViewRootImpl.mView;
+ final View root = getRootView();
if (root != null && isShown(root)) {
// trigger ACTION_OUTSIDE to notify windows
final long now = SystemClock.uptimeMillis();
@@ -882,12 +891,30 @@ public final class AccessibilityInteractionController {
private View findViewByAccessibilityId(int accessibilityId) {
if (accessibilityId == AccessibilityNodeInfo.ROOT_ITEM_ID) {
- return mViewRootImpl.mView;
+ return getRootView();
} else {
return AccessibilityNodeIdManager.getInstance().findView(accessibilityId);
}
}
+ private View getRootView() {
+ if (!isVisibleToAccessibilityService(mViewRootImpl.mView)) {
+ return null;
+ }
+ return mViewRootImpl.mView;
+ }
+
+ private void setAccessibilityFetchFlags(int flags) {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
+ mA11yManager.setRequestFromAccessibilityTool(
+ (flags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) != 0);
+ }
+
+ private void resetAccessibilityFetchFlags() {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ mA11yManager.setRequestFromAccessibilityTool(false);
+ }
+
// The boundInScreen includes magnification effect, so we need to normalize it before
// determine the visibility.
private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
@@ -1706,7 +1733,7 @@ public final class AccessibilityInteractionController {
@Override
public boolean test(View view) {
- if (view.getId() == mViewId && isShown(view)) {
+ if (view.getId() == mViewId && isShown(view) && isVisibleToAccessibilityService(view)) {
mInfos.add(view.createAccessibilityNodeInfo());
}
return false;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index addbab07c478..2a0246b200eb 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -25,6 +25,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.BatteryState;
import android.hardware.SensorManager;
+import android.hardware.input.InputDeviceCountryCode;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.lights.LightsManager;
@@ -72,6 +73,8 @@ public final class InputDevice implements Parcelable {
private final int mSources;
private final int mKeyboardType;
private final KeyCharacterMap mKeyCharacterMap;
+ @InputDeviceCountryCode
+ private final int mCountryCode;
private final boolean mHasVibrator;
private final boolean mHasMicrophone;
private final boolean mHasButtonUnderPad;
@@ -462,8 +465,9 @@ public final class InputDevice implements Parcelable {
@VisibleForTesting
public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
- KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
- boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery) {
+ KeyCharacterMap keyCharacterMap, @InputDeviceCountryCode int countryCode,
+ boolean hasVibrator, boolean hasMicrophone, boolean hasButtonUnderPad,
+ boolean hasSensor, boolean hasBattery) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
@@ -475,6 +479,7 @@ public final class InputDevice implements Parcelable {
mSources = sources;
mKeyboardType = keyboardType;
mKeyCharacterMap = keyCharacterMap;
+ mCountryCode = countryCode;
mHasVibrator = hasVibrator;
mHasMicrophone = hasMicrophone;
mHasButtonUnderPad = hasButtonUnderPad;
@@ -495,6 +500,7 @@ public final class InputDevice implements Parcelable {
mIsExternal = in.readInt() != 0;
mSources = in.readInt();
mKeyboardType = in.readInt();
+ mCountryCode = in.readInt();
mHasVibrator = in.readInt() != 0;
mHasMicrophone = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
@@ -729,6 +735,16 @@ public final class InputDevice implements Parcelable {
}
/**
+ * Gets Country code associated with the device
+ *
+ * @hide
+ */
+ @InputDeviceCountryCode
+ public int getCountryCode() {
+ return mCountryCode;
+ }
+
+ /**
* Gets whether the device is capable of producing the list of keycodes.
* @param keys The list of android keycodes to check for.
* @return An array of booleans where each member specifies whether the device is capable of
@@ -1147,6 +1163,7 @@ public final class InputDevice implements Parcelable {
out.writeInt(mIsExternal ? 1 : 0);
out.writeInt(mSources);
out.writeInt(mKeyboardType);
+ out.writeInt(mCountryCode);
out.writeInt(mHasVibrator ? 1 : 0);
out.writeInt(mHasMicrophone ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0);
@@ -1178,7 +1195,8 @@ public final class InputDevice implements Parcelable {
description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
description.append(" Descriptor: ").append(mDescriptor).append("\n");
description.append(" Generation: ").append(mGeneration).append("\n");
- description.append(" Location: ").append(mIsExternal ? "external" : "built-in").append("\n");
+ description.append(" Location: ").append(mIsExternal ? "external" : "built-in").append(
+ "\n");
description.append(" Keyboard Type: ");
switch (mKeyboardType) {
@@ -1194,6 +1212,8 @@ public final class InputDevice implements Parcelable {
}
description.append("\n");
+ description.append(" Country Code: ").append(mCountryCode).append("\n");
+
description.append(" Has Vibrator: ").append(mHasVibrator).append("\n");
description.append(" Has Sensor: ").append(mHasSensor).append("\n");
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 48937770eddb..996dee0cd2da 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3085,6 +3085,45 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
/**
+ * Automatically determine whether the view should only allow interactions from
+ * {@link android.accessibilityservice.AccessibilityService}s with the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
+ * set to true.
+ *
+ * <p>
+ * Accessibility interactions from services without {@code isAccessibilityTool} set to true are
+ * disallowed for any of the following conditions:
+ * <li>this view's window sets {@link WindowManager.LayoutParams#FLAG_SECURE}.</li>
+ * <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
+ * <li>any parent of this view returns true from {@link #isAccessibilityDataPrivate()}.</li>
+ * </p>
+ */
+ public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0x00000000;
+
+ /**
+ * Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
+ * with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
+ * property set to true.
+ */
+ public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 0x00000001;
+
+ /**
+ * Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
+ * regardless of their
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
+ */
+ public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 0x00000002;
+
+ /** @hide */
+ @IntDef(prefix = { "ACCESSIBILITY_DATA_PRIVATE_" }, value = {
+ ACCESSIBILITY_DATA_PRIVATE_AUTO,
+ ACCESSIBILITY_DATA_PRIVATE_YES,
+ ACCESSIBILITY_DATA_PRIVATE_NO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AccessibilityDataPrivate {}
+
+ /**
* Mask for obtaining the bits which specify how to determine
* whether a view is important for accessibility.
*/
@@ -4527,6 +4566,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private CharSequence mAccessibilityPaneTitle;
/**
+ * Describes whether this view should only allow interactions from
+ * {@link android.accessibilityservice.AccessibilityService}s with the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
+ * set to true.
+ */
+ private int mExplicitAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
+ /** Used to calculate and cache {@link #isAccessibilityDataPrivate()}. */
+ private int mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
+
+ /**
* Specifies the id of a view for which this view serves as a label for
* accessibility purposes.
*/
@@ -5919,6 +5968,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setImportantForAccessibility(a.getInt(attr,
IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
break;
+ case R.styleable.View_accessibilityDataPrivate:
+ setAccessibilityDataPrivate(a.getInt(attr,
+ ACCESSIBILITY_DATA_PRIVATE_AUTO));
+ break;
case R.styleable.View_accessibilityLiveRegion:
setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
break;
@@ -8518,6 +8571,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* is responsible for handling this call.
* </p>
* <p>
+ * If this view sets {@link #isAccessibilityDataPrivate()} then this view should only append
+ * sensitive information to an event that also sets
+ * {@link AccessibilityEvent#isAccessibilityDataPrivate()}.
+ * </p>
+ * <p>
* <em>Note:</em> Accessibility events of certain types are not dispatched for
* populating the event text via this method. For details refer to {@link AccessibilityEvent}.
* </p>
@@ -10419,7 +10477,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
if ((mAttachInfo.mAccessibilityFetchFlags
- & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
+ & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS) != 0
&& Resources.resourceHasPackage(mID)) {
try {
String viewId = getResources().getResourceName(mID);
@@ -13200,6 +13258,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void setFilterTouchesWhenObscured(boolean enabled) {
setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
FILTER_TOUCHES_WHEN_OBSCURED);
+ calculateAccessibilityDataPrivate();
}
/**
@@ -14402,14 +14461,80 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@UnsupportedAppUsage
public boolean includeForAccessibility() {
if (mAttachInfo != null) {
+ if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
+ && isAccessibilityDataPrivate()) {
+ return false;
+ }
+
return (mAttachInfo.mAccessibilityFetchFlags
- & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
+ & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
|| isImportantForAccessibility();
}
return false;
}
/**
+ * Whether this view should restrict accessibility service access only to services that have the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
+ * set to true.
+ *
+ * <p>
+ * See default behavior provided by {@link #ACCESSIBILITY_DATA_PRIVATE_AUTO}. Otherwise,
+ * returns true for {@link #ACCESSIBILITY_DATA_PRIVATE_YES} or false for {@link
+ * #ACCESSIBILITY_DATA_PRIVATE_NO}.
+ * </p>
+ *
+ * @return True if this view should restrict accessibility service access to services that have
+ * the isAccessibilityTool property.
+ */
+ @ViewDebug.ExportedProperty(category = "accessibility")
+ public boolean isAccessibilityDataPrivate() {
+ if (mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_AUTO) {
+ calculateAccessibilityDataPrivate();
+ }
+ return mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_YES;
+ }
+
+ /**
+ * Calculate and cache the inferred value for {@link #isAccessibilityDataPrivate()}.
+ *
+ * <p>
+ * <strong>Note:</strong> This method needs to be called any time one of the below conditions
+ * changes, to recalculate the new value.
+ * </p>
+ */
+ void calculateAccessibilityDataPrivate() {
+ // Use the explicit value if set.
+ if (mExplicitAccessibilityDataPrivate != ACCESSIBILITY_DATA_PRIVATE_AUTO) {
+ mInferredAccessibilityDataPrivate = mExplicitAccessibilityDataPrivate;
+ } else if (mAttachInfo != null && mAttachInfo.mWindowSecure) {
+ // Views inside FLAG_SECURE windows default to accessibilityDataPrivate.
+ mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
+ } else if (getFilterTouchesWhenObscured()) {
+ // Views that set filterTouchesWhenObscured default to accessibilityDataPrivate.
+ mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
+ } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataPrivate()) {
+ // Descendants of an accessibilityDataPrivate View are also accessibilityDataPrivate.
+ mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
+ } else {
+ // Otherwise, default to not accessibilityDataPrivate.
+ mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_NO;
+ }
+ }
+
+ /**
+ * Specifies whether this view should only allow interactions from
+ * {@link android.accessibilityservice.AccessibilityService}s with the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
+ * set to true.
+ */
+ public void setAccessibilityDataPrivate(
+ @AccessibilityDataPrivate int accessibilityDataPrivate) {
+ mExplicitAccessibilityDataPrivate = accessibilityDataPrivate;
+ calculateAccessibilityDataPrivate();
+ }
+
+ /**
* Returns whether the View is considered actionable from
* accessibility perspective. Such view are important for
* accessibility.
@@ -30096,6 +30221,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int mWindowVisibility;
/**
+ * Indicates whether the view's window sets {@link WindowManager.LayoutParams#FLAG_SECURE}.
+ */
+ boolean mWindowSecure;
+
+ /**
* Indicates the time at which drawing started to occur.
*/
@UnsupportedAppUsage
@@ -30272,8 +30402,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Flags related to accessibility processing.
*
- * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
- * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
+ * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
+ * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
*/
int mAccessibilityFetchFlags;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9f0ad1169a8e..c4f20dc25904 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3919,6 +3919,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
+ void calculateAccessibilityDataPrivate() {
+ super.calculateAccessibilityDataPrivate();
+ for (int i = 0; i < mChildrenCount; i++) {
+ mChildren[i].calculateAccessibilityDataPrivate();
+ }
+ }
+
+ @Override
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
void dispatchDetachedFromWindow() {
// If we still have a touch target, we are still in the process of
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 59bc061f54aa..ba250b0e247e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2836,6 +2836,7 @@ public final class ViewRootImpl implements ViewParent,
// However, windows are now always 32 bits by default, so choose 32 bits
mAttachInfo.mUse32BitDrawingCache = true;
mAttachInfo.mWindowVisibility = viewVisibility;
+ mAttachInfo.mWindowSecure = (lp.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0;
mAttachInfo.mRecomputeGlobalAttributes = false;
mLastConfigurationFromResources.setTo(config);
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index cd0dd1df1249..2db0dcbce45e 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -46,15 +46,17 @@ import java.util.List;
* </p>
* <p>
* The main purpose of an accessibility event is to communicate changes in the UI to an
- * {@link android.accessibilityservice.AccessibilityService}. The service may then inspect,
- * if needed the user interface by examining the View hierarchy, as represented by a tree of
- * {@link AccessibilityNodeInfo}s (snapshot of a View state)
- * which can be used for exploring the window content. Note that the privilege for accessing
- * an event's source, thus the window content, has to be explicitly requested. For more
+ * {@link android.accessibilityservice.AccessibilityService}. If needed, the service may then
+ * inspect the user interface by examining the View hierarchy through the event's
+ * {@link #getSource() source}, as represented by a tree of {@link AccessibilityNodeInfo}s (snapshot
+ * of a View state) which can be used for exploring the window content. Note that the privilege for
+ * accessing an event's source, thus the window content, has to be explicitly requested. For more
* details refer to {@link android.accessibilityservice.AccessibilityService}. If an
* accessibility service has not requested to retrieve the window content the event will
- * not contain reference to its source. Also for events of type
- * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available.
+ * not contain reference to its source. <strong>Note: </strong> for events of type
+ * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available, and Views that set
+ * {@link android.view.View#isAccessibilityDataPrivate()} may not populate all event properties on
+ * events sent from higher up in the view hierarchy.
* </p>
* <p>
* This class represents various semantically different accessibility event
@@ -1092,6 +1094,47 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
/**
+ * Whether the event should only be delivered to an
+ * {@link android.accessibilityservice.AccessibilityService} with the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
+ * set to true.
+ *
+ * <p>
+ * Initial value matches the {@link android.view.View#isAccessibilityDataPrivate} property from
+ * the event's source node, if present, or false by default.
+ * </p>
+ *
+ * @return True if the event should be delivered only to isAccessibilityTool services, false
+ * otherwise.
+ * @see #setAccessibilityDataPrivate
+ */
+ @Override
+ public boolean isAccessibilityDataPrivate() {
+ return super.isAccessibilityDataPrivate();
+ }
+
+ /**
+ * Sets whether the event should only be delivered to an
+ * {@link android.accessibilityservice.AccessibilityService} with the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
+ * set to true.
+ *
+ * <p>
+ * This will be set automatically based on the event's source (if present). If creating and
+ * sending an event directly through {@link AccessibilityManager} (where an event may have
+ * no source) then this method must be called explicitly if you want non-default behavior.
+ * </p>
+ *
+ * @param accessibilityDataPrivate True if the event should be delivered only to
+ * isAccessibilityTool services, false otherwise.
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ @Override
+ public void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
+ super.setAccessibilityDataPrivate(accessibilityDataPrivate);
+ }
+
+ /**
* Gets the bit mask of the speech state signaled by a {@link #TYPE_SPEECH_STATE_CHANGE} event
*
* @see #SPEECH_STATE_SPEAKING_START
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 9e3195aec8a6..e89f836aaac1 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -276,6 +276,8 @@ public final class AccessibilityManager {
private final ArrayMap<AudioDescriptionRequestedChangeListener, Executor>
mAudioDescriptionRequestedChangeListeners = new ArrayMap<>();
+ private boolean mRequestFromAccessibilityTool;
+
/**
* Map from a view's accessibility id to the list of request preparers set for that view
*/
@@ -983,6 +985,39 @@ public final class AccessibilityManager {
}
/**
+ * Whether the current accessibility request comes from an
+ * {@link AccessibilityService} with the {@link AccessibilityServiceInfo#isAccessibilityTool}
+ * property set to true.
+ *
+ * <p>
+ * You can use this method inside {@link AccessibilityNodeProvider} to decide how to populate
+ * your nodes.
+ * </p>
+ *
+ * <p>
+ * <strong>Note:</strong> The return value is valid only when an {@link AccessibilityNodeInfo}
+ * request is in progress, can change from one request to another, and has no meaning when a
+ * request is not in progress.
+ * </p>
+ *
+ * @return True if the current request is from a tool that sets isAccessibilityTool.
+ */
+ public boolean isRequestFromAccessibilityTool() {
+ return mRequestFromAccessibilityTool;
+ }
+
+ /**
+ * Specifies whether the current accessibility request comes from an
+ * {@link AccessibilityService} with the {@link AccessibilityServiceInfo#isAccessibilityTool}
+ * property set to true.
+ *
+ * @hide
+ */
+ public void setRequestFromAccessibilityTool(boolean requestFromAccessibilityTool) {
+ mRequestFromAccessibilityTool = requestFromAccessibilityTool;
+ }
+
+ /**
* Registers a {@link AccessibilityRequestPreparer}.
*/
public void addAccessibilityRequestPreparer(AccessibilityRequestPreparer preparer) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5d527500ff7b..6ae59bf0c8fc 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -220,14 +220,29 @@ public class AccessibilityNodeInfo implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface PrefetchingStrategy {}
- /** @hide */
- public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000080;
+ /**
+ * @see AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
+ * @hide
+ */
+ public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000080;
- /** @hide */
- public static final int FLAG_REPORT_VIEW_IDS = 0x00000100;
+ /**
+ * @see AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS
+ * @hide
+ */
+ public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 0x00000100;
+
+ /**
+ * @see AccessibilityServiceInfo#isAccessibilityTool()
+ * @hide
+ */
+ public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 0x00000200;
/** @hide */
- public static final int FLAG_REPORT_MASK = 0x00000180;
+ public static final int FLAG_REPORT_MASK =
+ FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
+ | FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
+ | FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
// Actions.
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 036316e15cb9..789c740bbba2 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -72,6 +72,7 @@ public class AccessibilityRecord {
private static final int PROPERTY_FULL_SCREEN = 0x00000080;
private static final int PROPERTY_SCROLLABLE = 0x00000100;
private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
+ private static final int PROPERTY_ACCESSIBILITY_DATA_PRIVATE = 0x00000400;
private static final int GET_SOURCE_PREFETCH_FLAGS =
AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
@@ -159,6 +160,8 @@ public class AccessibilityRecord {
important = root.isImportantForAccessibility();
rootViewId = root.getAccessibilityViewId();
mSourceWindowId = root.getAccessibilityWindowId();
+ setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE,
+ root.isAccessibilityDataPrivate());
}
setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
@@ -388,6 +391,23 @@ public class AccessibilityRecord {
}
/**
+ * @see AccessibilityEvent#isAccessibilityDataPrivate
+ * @hide
+ */
+ boolean isAccessibilityDataPrivate() {
+ return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE);
+ }
+
+ /**
+ * @see AccessibilityEvent#setAccessibilityDataPrivate
+ * @hide
+ */
+ void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
+ enforceNotSealed();
+ setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE, accessibilityDataPrivate);
+ }
+
+ /**
* Gets the number of items that can be visited.
*
* @return The number of items.
@@ -941,6 +961,8 @@ public class AccessibilityRecord {
appendUnless(false, PROPERTY_CHECKED, builder);
appendUnless(false, PROPERTY_FULL_SCREEN, builder);
appendUnless(false, PROPERTY_SCROLLABLE, builder);
+ appendUnless(false, PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, builder);
+ appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_PRIVATE, builder);
append(builder, "BeforeText", mBeforeText);
append(builder, "FromIndex", mFromIndex);
@@ -974,6 +996,8 @@ public class AccessibilityRecord {
case PROPERTY_SCROLLABLE: return "Scrollable";
case PROPERTY_IMPORTANT_FOR_ACCESSIBILITY:
return "ImportantForAccessibility";
+ case PROPERTY_ACCESSIBILITY_DATA_PRIVATE:
+ return "AccessibilityDataPrivate";
default: return Integer.toHexString(prop);
}
}
diff --git a/core/java/android/view/accessibility/DirectAccessibilityConnection.java b/core/java/android/view/accessibility/DirectAccessibilityConnection.java
index 71746ee5dbab..dcc5660a64d6 100644
--- a/core/java/android/view/accessibility/DirectAccessibilityConnection.java
+++ b/core/java/android/view/accessibility/DirectAccessibilityConnection.java
@@ -55,8 +55,8 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
// 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;
+ AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
+ | AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_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;
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index e31eabb083e5..0b63c179d042 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -303,6 +303,10 @@ public final class TextServicesManager {
/**
* Retrieve the list of currently enabled spell checkers.
*
+ * <p> Note: The results are filtered by the rules of
+ * <a href="/training/basics/intents/package-visibility">package visibility</a>, except for
+ * the currently active spell checker.
+ *
* @return The list of currently enabled spell checkers.
*/
@UserHandleAware
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cd1c23cdc75f..6a572c530a1e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12089,6 +12089,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
super.onPopulateAccessibilityEventInternal(event);
+ if (this.isAccessibilityDataPrivate() && !event.isAccessibilityDataPrivate()) {
+ // This view's accessibility data is private, but another view that generated this event
+ // is not, so don't append this view's text to the event in order to prevent sharing
+ // this view's contents with non-accessibility-tool services.
+ return;
+ }
+
final CharSequence text = getTextForAccessibility();
if (!TextUtils.isEmpty(text)) {
event.getText().add(text);
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 962870e733f7..6909965edcd8 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -17,25 +17,35 @@
package com.android.internal.os;
import android.annotation.Nullable;
-import android.os.BatteryStats;
+import android.os.BatteryManager;
+import android.os.BatteryStats.HistoryItem;
+import android.os.BatteryStats.HistoryStepDetails;
+import android.os.BatteryStats.HistoryTag;
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.function.Supplier;
+import java.util.concurrent.locks.ReentrantLock;
/**
* BatteryStatsHistory encapsulates battery history files.
@@ -56,57 +66,62 @@ import java.util.function.Supplier;
* 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
- public static final int VERSION = 208;
+ private static final int VERSION = 208;
- public static final String HISTORY_DIR = "battery-history";
- public static final String FILE_SUFFIX = ".bin";
+ private static final String HISTORY_DIR = "battery-history";
+ private 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.
- 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.
+ 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.
// Flag in delta int: a new battery level int follows.
- public static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
+ static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
// Flag in delta int: a new full state and battery status int follows.
- public static final int DELTA_STATE_FLAG = 0x00100000;
+ static final int DELTA_STATE_FLAG = 0x00100000;
// Flag in delta int: a new full state2 int follows.
- public static final int DELTA_STATE2_FLAG = 0x00200000;
+ static final int DELTA_STATE2_FLAG = 0x00200000;
// Flag in delta int: contains a wakelock or wakeReason tag.
- public static final int DELTA_WAKELOCK_FLAG = 0x00400000;
+ static final int DELTA_WAKELOCK_FLAG = 0x00400000;
// Flag in delta int: contains an event description.
- public static final int DELTA_EVENT_FLAG = 0x00800000;
+ static final int DELTA_EVENT_FLAG = 0x00800000;
// Flag in delta int: contains the battery charge count in uAh.
- public static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
+ static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
// These upper bits are the frequently changing state bits.
- public static final int DELTA_STATE_MASK = 0xfe000000;
+ 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.
- 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;
+ 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;
// We use the low bit of the battery state int to indicate that we have full details
// from a battery level change.
- public static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+ 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
- public static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
+ 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.
*/
@@ -144,19 +159,77 @@ 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 historyBuffer The in-memory history buffer.
- * @param systemDir typically /data/system
- * @param maxHistoryFiles the largest number of history buffer files to keep
+ * @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
*/
+ 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,
- Supplier<Integer> maxHistoryFiles) {
+ int maxHistoryFiles, int maxHistoryBufferSize,
+ HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
mHistoryBuffer = historyBuffer;
- mHistoryDir = new File(systemDir, HISTORY_DIR);
+ mSystemDir = systemDir;
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());
@@ -192,19 +265,81 @@ 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 Settings app or checkin file.
- * @param historyBuffer the history buffer
+ * such as a checkin file.
*/
- public BatteryStatsHistory(Parcel historyBuffer) {
- mHistoryDir = null;
+ private BatteryStatsHistory(Parcel historyBuffer,
+ HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
mHistoryBuffer = historyBuffer;
- mMaxHistoryFiles = null;
+ mClock = clock;
+ mSystemDir = null;
+ 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;
}
- public File getHistoryDirectory() {
- return mHistoryDir;
+ /**
+ * 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);
+ }
+
+ /**
+ * Returns true if this instance only supports reading history.
+ */
+ public boolean isReadOnly() {
+ return mActiveFile == null;
}
/**
@@ -221,12 +356,13 @@ 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));
}
/**
@@ -234,7 +370,7 @@ public class BatteryStatsHistory {
* create next history file.
*/
public void startNextFile() {
- if (mMaxHistoryFiles == null) {
+ if (mMaxHistoryFiles == 0) {
Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history");
return;
}
@@ -264,7 +400,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.get()) {
+ while (mFileNumbers.size() > mMaxHistoryFiles) {
int oldest = mFileNumbers.get(0);
getFile(oldest).delete();
mFileNumbers.remove(0);
@@ -272,36 +408,43 @@ public class BatteryStatsHistory {
}
/**
- * Delete all existing history files. Active history file start from number 0 again.
+ * Clear history buffer and delete all existing history files. Active history file start from
+ * number 0 again.
*/
- public void resetAllFiles() {
+ public void reset() {
+ if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!");
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 boolean startIteratingHistory() {
+ public BatteryStatsHistoryIterator iterate() {
mRecordCount = 0;
mCurrentFileIndex = 0;
mCurrentParcel = null;
mCurrentParcelEnd = 0;
mParcelIndex = 0;
- return true;
+ mBatteryStatsHistoryIterator = new BatteryStatsHistoryIterator(this);
+ return mBatteryStatsHistoryIterator;
}
/**
* Finish iterating history files and history buffer.
*/
- public void finishIteratingHistory() {
+ 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);
}
@@ -311,11 +454,12 @@ 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(BatteryStats.HistoryItem out) {
+ public Parcel getNextParcel(HistoryItem out) {
if (mRecordCount == 0) {
// reset out if it is the first record.
out.clear();
@@ -323,8 +467,7 @@ 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;
@@ -389,7 +532,8 @@ 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.
*/
@@ -402,8 +546,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);
@@ -413,6 +557,7 @@ 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.
*/
@@ -428,18 +573,68 @@ 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) {
@@ -450,13 +645,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);
@@ -480,17 +675,55 @@ public class BatteryStatsHistory {
Parcel historyBuffer = Parcel.obtain();
historyBuffer.unmarshall(historyBlob, 0, historyBlob.length);
- BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer);
+ BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer, null,
+ Clock.SYSTEM_CLOCK);
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 */);
}
@@ -498,7 +731,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;
@@ -521,10 +754,12 @@ public class BatteryStatsHistory {
return stats.getAvailableBytes() > MIN_FREE_SPACE;
}
+ @VisibleForTesting
public List<Integer> getFilesNumbers() {
return mFileNumbers;
}
+ @VisibleForTesting
public AtomicFile getActiveFile() {
return mActiveFile;
}
@@ -534,15 +769,972 @@ 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 de8b414c4b78..1bf878cb9119 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -36,7 +36,6 @@ public class BatteryStatsHistoryIterator {
public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) {
mBatteryStatsHistory = history;
- mBatteryStatsHistory.startIteratingHistory();
}
/**
@@ -231,4 +230,11 @@ 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.bp b/core/jni/Android.bp
index 4bc946e17d04..5498769fcf8f 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -80,6 +80,10 @@ cc_library_shared {
"include",
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_target_shared",
+ ],
+
target: {
android: {
srcs: [
@@ -243,7 +247,6 @@ cc_library_shared {
],
shared_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-types-aidl-cpp",
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 9cc72437a023..aece8c35a9e6 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -69,9 +69,9 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
static_cast<int32_t>(ident.product), descriptorObj.get(),
deviceInfo.isExternal(), deviceInfo.getSources(),
deviceInfo.getKeyboardType(), kcmObj.get(),
- deviceInfo.hasVibrator(), hasMic,
- deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(),
- deviceInfo.hasBattery()));
+ deviceInfo.getCountryCode(), deviceInfo.hasVibrator(),
+ hasMic, deviceInfo.hasButtonUnderPad(),
+ deviceInfo.hasSensor(), deviceInfo.hasBattery()));
const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
for (const InputDeviceInfo::MotionRange& range: ranges) {
@@ -94,7 +94,7 @@ int register_android_view_InputDevice(JNIEnv* env)
gInputDeviceClassInfo.ctor =
GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
"(IIILjava/lang/String;IILjava/lang/"
- "String;ZIILandroid/view/KeyCharacterMap;ZZZZZ)V");
+ "String;ZIILandroid/view/KeyCharacterMap;IZZZZZ)V");
gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
"addMotionRange", "(IIFFFFF)V");
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
index 3e1db364cd82..e13a3323d31a 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
@@ -23,7 +23,6 @@ import static com.google.common.truth.Truth.assertThat;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -114,8 +113,8 @@ public class InputDeviceLightsManagerTest {
return new InputDevice(id, 0 /* generation */, 0 /* controllerNumber */, "name",
0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
- false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
- false /* hasSensor */, false /* hasBattery */);
+ InputDeviceCountryCode.INVALID, false /* hasVibrator */, false /* hasMicrophone */,
+ false /* hasButtonUnderpad */, false /* hasSensor */, false /* hasBattery */);
}
private void mockLights(Light[] lights) throws Exception {
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
index 341ee37aee39..54ee4349c3e1 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
@@ -148,8 +148,8 @@ public class InputDeviceSensorManagerTest {
InputDevice d = new InputDevice(id, 0 /* generation */, 0 /* controllerNumber */, "name",
0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
- false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
- true /* hasSensor */, false /* hasBattery */);
+ InputDeviceCountryCode.INVALID, false /* hasVibrator */, false /* hasMicrophone */,
+ false /* hasButtonUnderpad */, true /* hasSensor */, false /* hasBattery */);
assertTrue(d.hasSensor());
return d;
}
diff --git a/media/Android.bp b/media/Android.bp
index ec243bf2370a..7118afad975a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -35,8 +35,8 @@ aidl_interface {
"aidl/android/media/soundtrigger_middleware/SoundTriggerModuleDescriptor.aidl",
],
imports: [
- "android.media.audio.common.types-V1",
- "android.media.soundtrigger.types-V1",
+ "android.media.audio.common.types",
+ "android.media.soundtrigger.types",
"media_permission-aidl",
],
}
@@ -52,6 +52,7 @@ aidl_interface {
],
local_include_dir: "aidl",
srcs: [
+ "aidl/android/media/audio/common/AudioAttributes.aidl",
"aidl/android/media/audio/common/AudioChannelLayout.aidl",
"aidl/android/media/audio/common/AudioConfig.aidl",
"aidl/android/media/audio/common/AudioConfigBase.aidl",
@@ -63,6 +64,7 @@ aidl_interface {
"aidl/android/media/audio/common/AudioEncapsulationMetadataType.aidl",
"aidl/android/media/audio/common/AudioEncapsulationMode.aidl",
"aidl/android/media/audio/common/AudioEncapsulationType.aidl",
+ "aidl/android/media/audio/common/AudioFlag.aidl",
"aidl/android/media/audio/common/AudioFormatDescription.aidl",
"aidl/android/media/audio/common/AudioFormatType.aidl",
"aidl/android/media/audio/common/AudioGain.aidl",
@@ -122,8 +124,75 @@ aidl_interface {
version: "1",
imports: [],
},
+ // IMPORTANT: Update latest_android_media_audio_common_types every time
+ // you add the latest frozen version to versions_with_info
+ ],
+
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_media_audio_common_types = "android.media.audio.common.types-V2"
+
+// Modules that depend on android.media.audio.common.types directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+ name: "latest_android_media_audio_common_types_cpp_shared",
+ shared_libs: [
+ latest_android_media_audio_common_types + "-cpp",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_media_audio_common_types_cpp_export_shared",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
],
+ export_shared_lib_headers: [
+ latest_android_media_audio_common_types + "-cpp",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_media_audio_common_types_cpp_static",
+ static_libs: [
+ latest_android_media_audio_common_types + "-cpp",
+ ],
+}
+cc_defaults {
+ name: "latest_android_media_audio_common_types_cpp_export_static",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_static",
+ ],
+ export_static_lib_headers: [
+ latest_android_media_audio_common_types + "-cpp",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_media_audio_common_types_ndk_shared",
+ shared_libs: [
+ latest_android_media_audio_common_types + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_media_audio_common_types_ndk_static",
+ static_libs: [
+ latest_android_media_audio_common_types + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_media_audio_common_types_cpp_target_shared",
+ target: {
+ android: {
+ shared_libs: [
+ latest_android_media_audio_common_types + "-cpp",
+ ],
+ },
+ },
}
aidl_interface {
diff --git a/media/aidl/android/media/audio/common/AudioAttributes.aidl b/media/aidl/android/media/audio/common/AudioAttributes.aidl
new file mode 100644
index 000000000000..eb29e10ab3a5
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioAttributes.aidl
@@ -0,0 +1,59 @@
+/*
+ * 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.media.audio.common;
+
+import android.media.audio.common.AudioContentType;
+import android.media.audio.common.AudioFlag;
+import android.media.audio.common.AudioSource;
+import android.media.audio.common.AudioUsage;
+
+/**
+ * AudioAttributes give information about an audio stream that is more
+ * descriptive than stream type alone.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioAttributes {
+ /**
+ * Classifies the content of the audio signal using categories such as
+ * speech or music
+ */
+ AudioContentType contentType = AudioContentType.UNKNOWN;
+ /**
+ * Classifies the intended use of the audio signal using categories such as
+ * alarm or ringtone
+ */
+ AudioUsage usage = AudioUsage.UNKNOWN;
+ /**
+ * Classifies the audio source using categories such as voice uplink or
+ * remote submix
+ */
+ AudioSource source = AudioSource.DEFAULT;
+ /**
+ * Bitmask describing how playback is to be affected.
+ */
+ int flags = AudioFlag.NONE;
+ /**
+ * Tag is an additional use case qualifier complementing AudioUsage and
+ * AudioContentType. Tags are set by vendor-specific applications and must
+ * be prefixed by "VX_". Vendors must namespace their tag names using the
+ * name of their company to avoid conflicts. The namespace must use at least
+ * three characters, and must go directly after the "VX_" prefix.
+ * For example: "VX_MYCOMPANY_VR".
+ */
+ @utf8InCpp String[] tags;
+} \ No newline at end of file
diff --git a/media/aidl/android/media/audio/common/AudioFlag.aidl b/media/aidl/android/media/audio/common/AudioFlag.aidl
new file mode 100644
index 000000000000..b9d493e620ab
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioFlag.aidl
@@ -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 android.media.audio.common;
+
+/**
+ * Defines the audio flags that are used in AudioAttributes
+ */
+@Backing(type="int")
+@VintfStability
+enum AudioFlag {
+ NONE = 0x0,
+ /**
+ * Flag defining a behavior where the audibility of the sound will be
+ * ensured by the system. To ensure sound audibility, the system only uses
+ * built-in speakers or wired headphones and specifically excludes wireless
+ * audio devices. Note this flag should only be used for sounds subject to
+ * regulatory behaviors in some countries, such as for camera shutter sound,
+ * and not for routing behaviors.
+ */
+ AUDIBILITY_ENFORCED = 0x1 << 0,
+ /**
+ * Skipping 0x1 << 1. This was previously used for SECURE flag, but because
+ * the security feature was never implemented using this flag, and the flag
+ * was never made public, this value may be used for another flag.
+ */
+ /**
+ * Flag to enable when the stream is associated with SCO usage.
+ * Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
+ */
+ SCO = 0x1 << 2,
+ /**
+ * Flag defining a behavior where the system ensures that the playback of
+ * the sound will be compatible with its use as a broadcast for surrounding
+ * people and/or devices. Ensures audibility with no or minimal
+ * post-processing applied.
+ */
+ BEACON = 0x1 << 3,
+ /**
+ * Flag requesting the use of an output stream supporting hardware A/V
+ * synchronization.
+ */
+ HW_AV_SYNC = 0x1 << 4,
+ /**
+ * Flag requesting capture from the source used for hardware hotword
+ * detection. To be used with capture preset MediaRecorder.AudioSource
+ * HOTWORD or MediaRecorder.AudioSource.VOICE_RECOGNITION.
+ */
+ HW_HOTWORD = 0x1 << 5,
+ /**
+ * Flag requesting audible playback even under limited interruptions.
+ */
+ BYPASS_INTERRUPTION_POLICY = 0x1 << 6,
+ /**
+ * Flag requesting audible playback even when the underlying stream is muted
+ */
+ BYPASS_MUTE = 0x1 << 7,
+ /**
+ * Flag requesting a low latency path when creating an AudioTrack.
+ * When using this flag, the sample rate must match the native sample rate
+ * of the device. Effects processing is also unavailable.
+ */
+ LOW_LATENCY = 0x1 << 8,
+ /**
+ * Flag requesting a deep buffer path when creating an AudioTrack.
+ *
+ * A deep buffer path, if available, may consume less power and is
+ * suitable for media playback where latency is not a concern.
+ */
+ DEEP_BUFFER = 0x1 << 9,
+ /**
+ * Flag specifying that the audio shall not be captured by third-party apps
+ * with a MediaProjection.
+ */
+ NO_MEDIA_PROJECTION = 0x1 << 10,
+ /**
+ * Flag indicating force muting haptic channels.
+ */
+ MUTE_HAPTIC = 0x1 << 11,
+ /**
+ * Flag specifying that the audio shall not be captured by any apps, not
+ * even system apps.
+ */
+ NO_SYSTEM_CAPTURE = 0x1 << 12,
+ /**
+ * Flag requesting private audio capture.
+ */
+ CAPTURE_PRIVATE = 0x1 << 13,
+ /**
+ * Flag indicating the audio content has been processed to provide a virtual
+ * multichannel audio experience.
+ */
+ CONTENT_SPATIALIZED = 0x1 << 14,
+ /**
+ * Flag indicating the audio content is never to be spatialized.
+ */
+ NEVER_SPATIALIZE = 0x1 << 15,
+ /**
+ * Flag indicating the audio is part of a call redirection.
+ * Valid for playback and capture.
+ */
+ CALL_REDIRECTION = 0x1 << 16,
+} \ No newline at end of file
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioAttributes.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioAttributes.aidl
new file mode 100644
index 000000000000..6d5e234af08e
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioAttributes.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioAttributes {
+ android.media.audio.common.AudioContentType contentType = android.media.audio.common.AudioContentType.UNKNOWN;
+ android.media.audio.common.AudioUsage usage = android.media.audio.common.AudioUsage.UNKNOWN;
+ android.media.audio.common.AudioSource source = android.media.audio.common.AudioSource.DEFAULT;
+ int flags = 0;
+ @utf8InCpp String[] tags;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFlag.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFlag.aidl
new file mode 100644
index 000000000000..3138531d6545
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFlag.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+@Backing(type="int") @VintfStability
+enum AudioFlag {
+ NONE = 0,
+ AUDIBILITY_ENFORCED = 1,
+ SCO = 4,
+ BEACON = 8,
+ HW_AV_SYNC = 16,
+ HW_HOTWORD = 32,
+ BYPASS_INTERRUPTION_POLICY = 64,
+ BYPASS_MUTE = 128,
+ LOW_LATENCY = 256,
+ DEEP_BUFFER = 512,
+ NO_MEDIA_PROJECTION = 1024,
+ MUTE_HAPTIC = 2048,
+ NO_SYSTEM_CAPTURE = 4096,
+ CAPTURE_PRIVATE = 8192,
+ CONTENT_SPATIALIZED = 16384,
+ NEVER_SPATIALIZE = 32768,
+ CALL_REDIRECTION = 65536,
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6922637350d9..2547a963eb31 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2812,9 +2812,7 @@ public class AudioManager {
}
/**
- * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
- * headset; <var>false</var> disable A2DP audio
- * @deprecated Do not use.
+ * @deprecated Use {@link MediaRouter#selectRoute} instead.
*/
@Deprecated public void setBluetoothA2dpOn(boolean on){
}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index bb086d6839eb..dc093595b6a4 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -311,7 +311,7 @@ public class SoundPool extends PlayerBase {
int priority, int loop, float rate) {
// FIXME: b/174876164 implement device id for soundpool
baseStart(0);
- return _play(soundID, leftVolume, rightVolume, priority, loop, rate);
+ return _play(soundID, leftVolume, rightVolume, priority, loop, rate, getPlayerIId());
}
/**
@@ -512,7 +512,7 @@ public class SoundPool extends PlayerBase {
@NonNull Object/*AudioAttributes*/ attributes, @NonNull String opPackageName);
private native final int _play(int soundID, float leftVolume, float rightVolume,
- int priority, int loop, float rate);
+ int priority, int loop, float rate, int playerIId);
private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index bbb4d1fa76bc..b1c97300d08a 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -344,6 +344,16 @@ public class Tuner implements AutoCloseable {
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public Tuner(@NonNull Context context, @Nullable String tvInputSessionId,
@TvInputService.PriorityHintUseCaseType int useCase) {
+ mContext = context;
+ mTunerResourceManager = mContext.getSystemService(TunerResourceManager.class);
+
+ // The Tuner Resource Manager is only started when the device has the tuner feature.
+ if (mTunerResourceManager == null) {
+ throw new IllegalStateException(
+ "Tuner instance is created, but the device doesn't have tuner feature");
+ }
+
+ // This code will start tuner server if the device is running on the lazy tuner HAL.
nativeSetup();
sTunerVersion = nativeGetTunerVersion();
if (sTunerVersion == TunerVersionChecker.TUNER_VERSION_UNKNOWN) {
@@ -353,9 +363,6 @@ public class Tuner implements AutoCloseable {
+ TunerVersionChecker.getMajorVersion(sTunerVersion) + "."
+ TunerVersionChecker.getMinorVersion(sTunerVersion) + ".");
}
- mContext = context;
- mTunerResourceManager = (TunerResourceManager)
- context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE);
if (mHandler == null) {
mHandler = createEventHandler();
}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index e3e200fcd754..96a3781af3a8 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -160,7 +160,7 @@ cc_library_shared {
cc_library_shared {
name: "libmedia_tv_tuner",
-
+ min_sdk_version: "",
srcs: [
"android_media_tv_Tuner.cpp",
"tuner/DemuxClient.cpp",
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 397c70485d5b..244730b76df2 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1238,7 +1238,8 @@ FrontendClientCallbackImpl::~FrontendClientCallbackImpl() {
}
/////////////// Tuner ///////////////////////
-sp<TunerClient> JTuner::mTunerClient;
+sp<TunerClient> JTuner::sTunerClient = nullptr;
+std::mutex JTuner::sTunerClientMutex;
JTuner::JTuner(JNIEnv *env, jobject thiz) : mClass(nullptr) {
jclass clazz = env->GetObjectClass(thiz);
@@ -1246,10 +1247,15 @@ JTuner::JTuner(JNIEnv *env, jobject thiz) : mClass(nullptr) {
mClass = (jclass)env->NewGlobalRef(clazz);
mObject = env->NewWeakGlobalRef(thiz);
- if (mTunerClient == nullptr) {
- mTunerClient = new TunerClient();
+ {
+ std::scoped_lock<std::mutex> lock(sTunerClientMutex);
+ if (sTunerClient == nullptr) {
+ sTunerClient = new TunerClient();
+ } else {
+ sTunerClient->incStrong(this);
+ }
+ ALOGV("JTuner refs count: %d", sTunerClient->getStrongCount());
}
-
mSharedFeId = (int)Constant::INVALID_FRONTEND_ID;
}
@@ -1271,18 +1277,28 @@ JTuner::~JTuner() {
mFeClient = nullptr;
mFeClientCb = nullptr;
mDemuxClient = nullptr;
+ {
+ std::scoped_lock<std::mutex> lock(sTunerClientMutex);
+ int32_t refCnt = sTunerClient->getStrongCount();
+ ALOGV("~JTuner refs count: %d", refCnt);
+ if (refCnt == 1) {
+ sTunerClient = nullptr;
+ } else {
+ sTunerClient->decStrong(this);
+ }
+ }
mClass = nullptr;
mObject = nullptr;
}
jint JTuner::getTunerVersion() {
ALOGV("JTuner::getTunerVersion()");
- return (jint)mTunerClient->getHalTunerVersion();
+ return (jint)sTunerClient->getHalTunerVersion();
}
jobject JTuner::getFrontendIds() {
ALOGV("JTuner::getFrontendIds()");
- vector<int32_t> ids = mTunerClient->getFrontendIds();
+ vector<int32_t> ids = sTunerClient->getFrontendIds();
if (ids.size() == 0) {
ALOGW("Frontend isn't available");
return nullptr;
@@ -1305,7 +1321,7 @@ jobject JTuner::getFrontendIds() {
jobject JTuner::openFrontendByHandle(int feHandle) {
// TODO: Handle reopening frontend with different handle
- sp<FrontendClient> feClient = mTunerClient->openFrontend(feHandle);
+ sp<FrontendClient> feClient = sTunerClient->openFrontend(feHandle);
if (feClient == nullptr) {
ALOGE("Failed to open frontend");
return nullptr;
@@ -1511,7 +1527,7 @@ jobject JTuner::getDtmbFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jobject JTuner::getFrontendInfo(int id) {
shared_ptr<FrontendInfo> feInfo;
- feInfo = mTunerClient->getFrontendInfo(id);
+ feInfo = sTunerClient->getFrontendInfo(id);
if (feInfo == nullptr) {
return nullptr;
}
@@ -1605,21 +1621,21 @@ Result JTuner::getFrontendHardwareInfo(string &info) {
}
jint JTuner::setMaxNumberOfFrontends(int32_t type, int32_t maxNumber) {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
ALOGE("tuner is not initialized");
return (jint)Result::INVALID_STATE;
}
- return (jint)mTunerClient->setMaxNumberOfFrontends(static_cast<FrontendType>(type), maxNumber);
+ return (jint)sTunerClient->setMaxNumberOfFrontends(static_cast<FrontendType>(type), maxNumber);
}
int32_t JTuner::getMaxNumberOfFrontends(int32_t type) {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
ALOGE("tuner is not initialized");
return -1;
}
- return mTunerClient->getMaxNumberOfFrontends(static_cast<FrontendType>(type));
+ return sTunerClient->getMaxNumberOfFrontends(static_cast<FrontendType>(type));
}
jint JTuner::removeOutputPid(int32_t pid) {
@@ -1662,13 +1678,13 @@ jobjectArray JTuner::getFrontendStatusReadiness(jintArray types) {
}
jobject JTuner::openLnbByHandle(int handle) {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
return nullptr;
}
sp<LnbClient> lnbClient;
sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
- lnbClient = mTunerClient->openLnb(handle);
+ lnbClient = sTunerClient->openLnb(handle);
if (lnbClient == nullptr) {
ALOGD("Failed to open lnb, handle = %d", handle);
return nullptr;
@@ -1692,7 +1708,7 @@ jobject JTuner::openLnbByHandle(int handle) {
}
jobject JTuner::openLnbByName(jstring name) {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
return nullptr;
}
@@ -1700,7 +1716,7 @@ jobject JTuner::openLnbByName(jstring name) {
std::string lnbName(env->GetStringUTFChars(name, nullptr));
sp<LnbClient> lnbClient;
sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
- lnbClient = mTunerClient->openLnbByName(lnbName);
+ lnbClient = sTunerClient->openLnbByName(lnbName);
if (lnbClient == nullptr) {
ALOGD("Failed to open lnb by name, name = %s", lnbName.c_str());
return nullptr;
@@ -1770,20 +1786,20 @@ int JTuner::setLnb(sp<LnbClient> lnbClient) {
}
int JTuner::setLna(bool enable) {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
return (int)Result::NOT_INITIALIZED;
}
- Result result = mTunerClient->setLna(enable);
+ Result result = sTunerClient->setLna(enable);
return (int)result;
}
Result JTuner::openDemux(int handle) {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
return Result::NOT_INITIALIZED;
}
if (mDemuxClient == nullptr) {
- mDemuxClient = mTunerClient->openDemux(handle);
+ mDemuxClient = sTunerClient->openDemux(handle);
if (mDemuxClient == nullptr) {
ALOGE("Failed to open demux");
return Result::UNKNOWN_ERROR;
@@ -1881,10 +1897,10 @@ int JTuner::unlinkCiCam(int id) {
jobject JTuner::openDescrambler() {
ALOGV("JTuner::openDescrambler");
- if (mTunerClient == nullptr || mDemuxClient == nullptr) {
+ if (sTunerClient == nullptr || mDemuxClient == nullptr) {
return nullptr;
}
- sp<DescramblerClient> descramblerClient = mTunerClient->openDescrambler(0/*unused*/);
+ sp<DescramblerClient> descramblerClient = sTunerClient->openDescrambler(0 /*unused*/);
if (descramblerClient == nullptr) {
ALOGD("Failed to open descrambler");
@@ -1995,12 +2011,12 @@ jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
}
jobject JTuner::getDemuxCaps() {
- if (mTunerClient == nullptr) {
+ if (sTunerClient == nullptr) {
return nullptr;
}
shared_ptr<DemuxCapabilities> caps;
- caps = mTunerClient->getDemuxCaps();
+ caps = sTunerClient->getDemuxCaps();
if (caps == nullptr) {
return nullptr;
}
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 03e7fa91653d..c74b2df6c178 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -216,7 +216,8 @@ protected:
private:
jclass mClass;
jweak mObject;
- static sp<TunerClient> mTunerClient;
+ static sp<TunerClient> sTunerClient;
+ static std::mutex sTunerClientMutex;
sp<FrontendClient> mFeClient;
sp<FrontendClientCallbackImpl> mFeClientCb;
int mFeId;
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index a2826cb58ccf..9f32a83ad5be 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -115,7 +115,7 @@ bool SoundPool::unload(int32_t soundID)
}
int32_t SoundPool::play(int32_t soundID, float leftVolume, float rightVolume,
- int32_t priority, int32_t loop, float rate)
+ int32_t priority, int32_t loop, float rate, int32_t playerIId)
{
ALOGV("%s(soundID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f)",
__func__, soundID, leftVolume, rightVolume, priority, loop, rate);
@@ -136,8 +136,9 @@ int32_t SoundPool::play(int32_t soundID, float leftVolume, float rightVolume,
}
const int32_t streamID = mStreamManager.queueForPlay(
- sound, soundID, leftVolume, rightVolume, priority, loop, rate);
+ sound, soundID, leftVolume, rightVolume, priority, loop, rate, playerIId);
ALOGV("%s returned %d", __func__, streamID);
+
return streamID;
}
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 6bb971b07e43..efc358ddf3b2 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -39,7 +39,7 @@ public:
int32_t load(int fd, int64_t offset, int64_t length, int32_t priority);
bool unload(int32_t soundID);
int32_t play(int32_t soundID, float leftVolume, float rightVolume, int32_t priority,
- int32_t loop, float rate);
+ int32_t loop, float rate, int32_t playerIId = PLAYER_PIID_INVALID);
void pause(int32_t streamID);
void autoPause();
void resume(int32_t streamID);
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index 9ed8770a455c..4194a22bfb67 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -229,7 +229,7 @@ Stream* Stream::getPairStream() const
return mStreamManager->getPairStream(this);
}
-Stream* Stream::playPairStream(std::vector<std::any>& garbage) {
+Stream* Stream::playPairStream(std::vector<std::any>& garbage, int32_t playerIId) {
Stream* pairStream = getPairStream();
LOG_ALWAYS_FATAL_IF(pairStream == nullptr, "No pair stream!");
{
@@ -260,7 +260,7 @@ Stream* Stream::playPairStream(std::vector<std::any>& garbage) {
const int pairState = pairStream->mState;
pairStream->play_l(pairStream->mSound, pairStream->mStreamID,
pairStream->mLeftVolume, pairStream->mRightVolume, pairStream->mPriority,
- pairStream->mLoop, pairStream->mRate, garbage);
+ pairStream->mLoop, pairStream->mRate, garbage, playerIId);
if (pairStream->mState == IDLE) {
return nullptr; // AudioTrack error
}
@@ -274,12 +274,12 @@ Stream* Stream::playPairStream(std::vector<std::any>& garbage) {
void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate,
- std::vector<std::any>& garbage)
+ std::vector<std::any>& garbage, int32_t playerIId)
{
ALOGV("%s(%p)(soundID=%d, streamID=%d, leftVolume=%f, rightVolume=%f,"
- " priority=%d, loop=%d, rate=%f)",
+ " priority=%d, loop=%d, rate=%f, playerIId=%d)",
__func__, this, sound->getSoundID(), nextStreamID, leftVolume, rightVolume,
- priority, loop, rate);
+ priority, loop, rate, playerIId);
// initialize track
const audio_stream_type_t streamType =
@@ -340,6 +340,10 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
// MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL
mAudioTrack->setCallerName("soundpool");
+ if (playerIId != PLAYER_PIID_INVALID) {
+ mAudioTrack->setPlayerIId(playerIId);
+ }
+
if (status_t status = mAudioTrack->initCheck();
status != NO_ERROR) {
ALOGE("%s: error %d creating AudioTrack", __func__, status);
@@ -379,6 +383,7 @@ int Stream::getCorrespondingStreamID() {
std::lock_guard lock(mLock);
return static_cast<int>(mAudioTrack ? mStreamID : getPairStream()->mStreamID);
}
+
size_t Stream::StreamCallback::onMoreData(const AudioTrack::Buffer&) {
ALOGW("%s streamID %d Unexpected EVENT_MORE_DATA for static track",
__func__, mStream->getCorrespondingStreamID());
diff --git a/media/jni/soundpool/Stream.h b/media/jni/soundpool/Stream.h
index 0054eeca529a..6c9ef2e087f8 100644
--- a/media/jni/soundpool/Stream.h
+++ b/media/jni/soundpool/Stream.h
@@ -93,7 +93,8 @@ public:
// returns the pair stream if successful, nullptr otherwise.
// garbage is used to release tracks and data outside of any lock.
- Stream* playPairStream(std::vector<std::any>& garbage);
+ Stream* playPairStream(std::vector<std::any>& garbage,
+ int32_t playerIId = PLAYER_PIID_INVALID);
// These parameters are explicitly checked in the SoundPool class
// so never deviate from the Java API specified values.
@@ -157,7 +158,7 @@ private:
// garbage is used to release tracks and data outside of any lock.
void play_l(const std::shared_ptr<Sound>& sound, int streamID,
float leftVolume, float rightVolume, int priority, int loop, float rate,
- std::vector<std::any>& garbage) REQUIRES(mLock);
+ std::vector<std::any>& garbage, int playerIId) REQUIRES(mLock);
void stop_l() REQUIRES(mLock);
void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 487a696d8765..acd4badad9b0 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -151,10 +151,13 @@ StreamManager::~StreamManager()
int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
int32_t soundID, float leftVolume, float rightVolume,
- int32_t priority, int32_t loop, float rate)
+ int32_t priority, int32_t loop, float rate, int32_t playerIId)
{
- ALOGV("%s(sound=%p, soundID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f)",
- __func__, sound.get(), soundID, leftVolume, rightVolume, priority, loop, rate);
+ ALOGV(
+ "%s(sound=%p, soundID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f,"
+ " playerIId=%d)", __func__, sound.get(), soundID, leftVolume, rightVolume, priority,
+ loop, rate, playerIId);
+
bool launchThread = false;
int32_t streamID = 0;
std::vector<std::any> garbage;
@@ -244,7 +247,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
removeFromQueues_l(newStream);
mProcessingStreams.emplace(newStream);
lock.unlock();
- if (Stream* nextStream = newStream->playPairStream(garbage)) {
+ if (Stream* nextStream = newStream->playPairStream(garbage, playerIId)) {
lock.lock();
ALOGV("%s: starting streamID:%d", __func__, nextStream->getStreamID());
addToActiveQueue_l(nextStream);
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index ec65b0c49dc4..adbab4b0f9d9 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -394,7 +394,7 @@ public:
// Returns positive streamID on success, 0 on failure. This is locked.
int32_t queueForPlay(const std::shared_ptr<Sound> &sound,
int32_t soundID, float leftVolume, float rightVolume,
- int32_t priority, int32_t loop, float rate)
+ int32_t priority, int32_t loop, float rate, int32_t playerIId)
NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
///////////////////////////////////////////////////////////////////////
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 5264772be7c3..25040a942061 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -364,12 +364,19 @@ android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
static jint
android_media_SoundPool_play(JNIEnv *env, jobject thiz, jint sampleID,
jfloat leftVolume, jfloat rightVolume, jint priority, jint loop,
- jfloat rate)
+ jfloat rate, jint playerIId)
{
ALOGV("android_media_SoundPool_play\n");
auto soundPool = getSoundPool(env, thiz);
if (soundPool == nullptr) return 0;
- return (jint) soundPool->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
+
+ return (jint) soundPool->play(sampleID,
+ leftVolume,
+ rightVolume,
+ priority,
+ loop,
+ rate,
+ playerIId);
}
static void
@@ -563,7 +570,7 @@ static JNINativeMethod gMethods[] = {
(void *)android_media_SoundPool_unload
},
{ "_play",
- "(IFFIIF)I",
+ "(IFFIIFI)I",
(void *)android_media_SoundPool_play
},
{ "pause",
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index 3c8fdfe682af..8515874c022f 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -27,16 +27,13 @@ using ::aidl::android::hardware::tv::tuner::FrontendType;
namespace android {
-shared_ptr<ITunerService> TunerClient::mTunerService;
int32_t TunerClient::mTunerVersion;
/////////////// TunerClient ///////////////////////
TunerClient::TunerClient() {
- if (mTunerService == nullptr) {
- ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
- mTunerService = ITunerService::fromBinder(binder);
- }
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.tuner"));
+ mTunerService = ITunerService::fromBinder(binder);
if (mTunerService == nullptr) {
ALOGE("Failed to get tuner service");
} else {
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index a9f37e6df3aa..5410c1b185f5 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -150,10 +150,11 @@ public:
private:
/**
- * An AIDL Tuner Service Singleton assigned at the first time the Tuner Client
- * connects with the Tuner Service. Default null when the service does not exist.
+ * An AIDL Tuner Service assigned at the first time the Tuner Client connects with
+ * the Tuner Service. null when the service does not exist. The tuner client in JNI
+ * will be singleton, so this Tuner Service client will be singleton too.
*/
- static shared_ptr<ITunerService> mTunerService;
+ shared_ptr<ITunerService> mTunerService;
// An integer that carries the Tuner version. The high 16 bits are the major version number
// while the low 16 bits are the minor version. Default value is unknown version 0.
diff --git a/packages/SettingsLib/Spa/gallery/AndroidManifest.xml b/packages/SettingsLib/Spa/gallery/AndroidManifest.xml
index b5be7cd45688..22299861e0e3 100644
--- a/packages/SettingsLib/Spa/gallery/AndroidManifest.xml
+++ b/packages/SettingsLib/Spa/gallery/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:label="@string/app_label"
android:supportsRtl="true">
<activity
- android:name="com.android.settingslib.spa.gallery.MainActivity"
+ android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
index 51d3714ce5ee..12be0702b3ee 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
@@ -36,24 +36,28 @@ open class SpaActivity(
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_SpaLib_DayNight)
super.onCreate(savedInstanceState)
+
setContent {
- MainContent()
+ SettingsTheme {
+ MainContent()
+ }
}
}
@Composable
private fun MainContent() {
- SettingsTheme {
- val navController = rememberNavController()
- CompositionLocalProvider(navController.localNavController()) {
- NavHost(navController, settingsPageRepository.startDestination) {
- for (page in settingsPageRepository.allPages) {
- composable(
- route = page.route,
- arguments = page.arguments,
- ) { navBackStackEntry ->
- page.Page(navBackStackEntry.arguments)
- }
+ val startDestination =
+ intent?.getStringExtra(KEY_START_DESTINATION) ?: settingsPageRepository.startDestination
+
+ val navController = rememberNavController()
+ CompositionLocalProvider(navController.localNavController()) {
+ NavHost(navController, startDestination) {
+ for (page in settingsPageRepository.allPages) {
+ composable(
+ route = page.route,
+ arguments = page.arguments,
+ ) { navBackStackEntry ->
+ page.Page(navBackStackEntry.arguments)
}
}
}
@@ -62,4 +66,8 @@ open class SpaActivity(
private val SettingsPageProvider.route: String
get() = name + arguments.joinToString("") { argument -> "/{${argument.name}}" }
+
+ companion object {
+ const val KEY_START_DESTINATION = "spa:SpaActivity:startDestination"
+ }
}
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 26feaf979b20..234ef241f538 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -52,17 +52,6 @@
]
},
{
- "name": "SystemUIGoogleScreenshotTests",
- "options": [
- {
- "exclude-annotation": "org.junit.Ignore"
- },
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
- },
- {
// Permission indicators
"name": "CtsPermission4TestCases",
"options": [
diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json
new file mode 100644
index 000000000000..c5ed827de0d1
--- /dev/null
+++ b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":80,"h":80,"nm":"RearFPS_error_to_success","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[28,47,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-10.556,-9.889],[7.444,6.555],[34.597,-20.486]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":10,"op":910,"st":10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[39.95,40,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.721,-7.982],[1.721,-7.982],[1.721,7.5],[-1.721,7.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.002,32.488],"ix":2},"a":{"a":0,"k":[0.002,7.488],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.659,0.6],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.6,0.92],"y":[1,1.096]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[100,110]},{"t":10,"s":[100,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top!","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.681,-1.25],[1.681,-1.25],[1.681,2.213],[-1.681,2.213]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30,38.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.6,0.6],"y":[1,1]},"o":{"x":[0.853,0.853],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.92,0.92],"y":[1.06,1.06]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[110,110]},{"t":10,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom!","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":86,"st":-30,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[93.5,93.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[4]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":10,"op":21,"st":10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[93.5,93.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[4]},{"t":10,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":10,"st":0,"bm":0}],"markers":[]} \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json
new file mode 100644
index 000000000000..3eb95ef1a718
--- /dev/null
+++ b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":80,"h":80,"nm":"RearFPS_fingerprint_to_success","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[28,47,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-10.556,-9.889],[7.444,6.555],[34.597,-20.486]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":10,"op":910,"st":10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[93.5,93.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[4]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":10,"op":21,"st":10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40.091,40,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-0.386],[4.642,1.931],[2.07,2.703],[-0.001,2.886],[-2.621,2.591],[-4.909,1.813],[-8.182,-0.386]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.278431385756,0.278431385756,0.278431385756,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":20,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index d718a240bbfd..6c452bd97ff6 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -45,7 +45,7 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
fun e(@CompileTimeConstant msg: String) = log(msg, ERROR)
- fun v(@CompileTimeConstant msg: String) = log(msg, ERROR)
+ fun v(@CompileTimeConstant msg: String) = log(msg, VERBOSE)
fun w(@CompileTimeConstant msg: String) = log(msg, WARNING)
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardViewMediatorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardViewMediatorLogger.kt
new file mode 100644
index 000000000000..f54bf026a686
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardViewMediatorLogger.kt
@@ -0,0 +1,690 @@
+/*
+ * 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.keyguard.logging
+
+import android.os.RemoteException
+import android.view.WindowManagerPolicyConstants
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
+import com.android.systemui.log.LogLevel.WTF
+import com.android.systemui.log.dagger.KeyguardViewMediatorLog
+import javax.inject.Inject
+
+private const val TAG = "KeyguardViewMediatorLog"
+
+@SysUISingleton
+class KeyguardViewMediatorLogger @Inject constructor(
+ @KeyguardViewMediatorLog private val logBuffer: LogBuffer,
+) {
+
+ fun logFailedLoadLockSound(soundPath: String) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { str1 = soundPath },
+ { "failed to load lock sound from $str1" }
+ )
+ }
+
+ fun logFailedLoadUnlockSound(soundPath: String) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { str1 = soundPath },
+ { "failed to load unlock sound from $str1" }
+ )
+ }
+
+ fun logFailedLoadTrustedSound(soundPath: String) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { str1 = soundPath },
+ { "failed to load trusted sound from $str1" }
+ )
+ }
+
+ fun logOnSystemReady() {
+ logBuffer.log(TAG, DEBUG, "onSystemReady")
+ }
+
+ fun logOnStartedGoingToSleep(offReason: Int) {
+ val offReasonString = WindowManagerPolicyConstants.offReasonToString(offReason)
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { str1 = offReasonString },
+ { "onStartedGoingToSleep($str1)" }
+ )
+ }
+
+ fun logPendingExitSecureCallbackCancelled() {
+ logBuffer.log(TAG, DEBUG, "pending exit secure callback cancelled")
+ }
+
+ fun logFailedOnKeyguardExitResultFalse(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onKeyguardExitResult(false)",
+ remoteException
+ )
+ }
+
+ fun logOnFinishedGoingToSleep(offReason: Int) {
+ val offReasonString = WindowManagerPolicyConstants.offReasonToString(offReason)
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { str1 = offReasonString },
+ { "onFinishedGoingToSleep($str1)" }
+ )
+ }
+
+ fun logPinLockRequestedStartingKeyguard() {
+ logBuffer.log(TAG, INFO, "PIN lock requested, starting keyguard")
+ }
+
+ fun logUserSwitching(userId: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = userId },
+ { "onUserSwitching $int1" }
+ )
+ }
+
+ fun logOnUserSwitchComplete(userId: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = userId },
+ { "onUserSwitchComplete $int1" }
+ )
+ }
+
+ fun logOnSimStateChanged(subId: Int, slotId: Int, simState: String) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = subId
+ int2 = slotId
+ str1 = simState
+ },
+ { "onSimStateChanged(subId=$int1, slotId=$int2, state=$str1)" }
+ )
+ }
+
+ fun logFailedToCallOnSimSecureStateChanged(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onSimSecureStateChanged",
+ remoteException
+ )
+ }
+
+ fun logIccAbsentIsNotShowing() {
+ logBuffer.log(TAG, DEBUG, "ICC_ABSENT isn't showing, we need to show the " +
+ "keyguard since the device isn't provisioned yet.")
+ }
+
+ fun logSimMovedToAbsent() {
+ logBuffer.log(TAG, DEBUG, "SIM moved to ABSENT when the " +
+ "previous state was locked. Reset the state.")
+ }
+
+ fun logIntentValueIccLocked() {
+ logBuffer.log(TAG, DEBUG, "INTENT_VALUE_ICC_LOCKED and keyguard isn't " +
+ "showing; need to show keyguard so user can enter sim pin")
+ }
+
+ fun logPermDisabledKeyguardNotShowing() {
+ logBuffer.log(TAG, DEBUG, "PERM_DISABLED and keyguard isn't showing.")
+ }
+
+ fun logPermDisabledResetStateLocked() {
+ logBuffer.log(TAG, DEBUG, "PERM_DISABLED, resetStateLocked to show permanently " +
+ "disabled message in lockscreen.")
+ }
+
+ fun logReadyResetState(showing: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = showing },
+ { "READY, reset state? $bool1"}
+ )
+ }
+
+ fun logSimMovedToReady() {
+ logBuffer.log(TAG, DEBUG, "SIM moved to READY when the previously was locked. " +
+ "Reset the state.")
+ }
+
+ fun logUnspecifiedSimState(simState: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = simState },
+ { "Unspecific state: $int1" }
+ )
+ }
+
+ fun logOccludeLaunchAnimationCancelled(occluded: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = occluded },
+ { "Occlude launch animation cancelled. Occluded state is now: $bool1"}
+ )
+ }
+
+ fun logActivityLaunchAnimatorLaunchContainerChanged() {
+ logBuffer.log(TAG, WTF, "Someone tried to change the launch container for the " +
+ "ActivityLaunchAnimator, which should never happen.")
+ }
+
+ fun logVerifyUnlock() {
+ logBuffer.log(TAG, DEBUG, "verifyUnlock")
+ }
+
+ fun logIgnoreUnlockDeviceNotProvisioned() {
+ logBuffer.log(TAG, DEBUG, "ignoring because device isn't provisioned")
+ }
+
+ fun logFailedToCallOnKeyguardExitResultFalse(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onKeyguardExitResult(false)",
+ remoteException
+ )
+ }
+
+ fun logVerifyUnlockCalledNotExternallyDisabled() {
+ logBuffer.log(TAG, WARNING, "verifyUnlock called when not externally disabled")
+ }
+
+ fun logSetOccluded(isOccluded: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = isOccluded },
+ { "setOccluded($bool1)" }
+ )
+ }
+
+ fun logHandleSetOccluded(isOccluded: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = isOccluded },
+ { "handleSetOccluded($bool1)" }
+ )
+ }
+
+ fun logIgnoreHandleShow() {
+ logBuffer.log(TAG, DEBUG, "ignoring handleShow because system is not ready.")
+ }
+
+ fun logHandleShow() {
+ logBuffer.log(TAG, DEBUG, "handleShow")
+ }
+
+ fun logHandleHide() {
+ logBuffer.log(TAG, DEBUG, "handleHide")
+ }
+
+ fun logSplitSystemUserQuitUnlocking() {
+ logBuffer.log(TAG, DEBUG, "Split system user, quit unlocking.")
+ }
+
+ fun logHandleStartKeyguardExitAnimation(startTime: Long, fadeoutDuration: Long) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ long1 = startTime
+ long2 = fadeoutDuration
+ },
+ { "handleStartKeyguardExitAnimation startTime=$long1 fadeoutDuration=$long2" }
+ )
+ }
+
+ fun logHandleVerifyUnlock() {
+ logBuffer.log(TAG, DEBUG, "handleVerifyUnlock")
+ }
+
+ fun logHandleNotifyStartedGoingToSleep() {
+ logBuffer.log(TAG, DEBUG, "handleNotifyStartedGoingToSleep")
+ }
+
+ fun logHandleNotifyFinishedGoingToSleep() {
+ logBuffer.log(TAG, DEBUG, "handleNotifyFinishedGoingToSleep")
+ }
+
+ fun logHandleNotifyWakingUp() {
+ logBuffer.log(TAG, DEBUG, "handleNotifyWakingUp")
+ }
+
+ fun logHandleReset() {
+ logBuffer.log(TAG, DEBUG, "handleReset")
+ }
+
+ fun logKeyguardDone() {
+ logBuffer.log(TAG, DEBUG, "keyguardDone")
+ }
+
+ fun logKeyguardDonePending() {
+ logBuffer.log(TAG, DEBUG, "keyguardDonePending")
+ }
+
+ fun logKeyguardGone() {
+ logBuffer.log(TAG, DEBUG, "keyguardGone")
+ }
+
+ fun logUnoccludeAnimationCancelled(isOccluded: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = isOccluded },
+ { "Unocclude animation cancelled. Occluded state is now: $bool1" }
+ )
+ }
+
+ fun logShowLocked() {
+ logBuffer.log(TAG, DEBUG, "showLocked")
+ }
+
+ fun logHideLocked() {
+ logBuffer.log(TAG, DEBUG, "hideLocked")
+ }
+
+ fun logResetStateLocked() {
+ logBuffer.log(TAG, DEBUG, "resetStateLocked")
+ }
+
+ fun logNotifyStartedGoingToSleep() {
+ logBuffer.log(TAG, DEBUG, "notifyStartedGoingToSleep")
+ }
+
+ fun logNotifyFinishedGoingToSleep() {
+ logBuffer.log(TAG, DEBUG, "notifyFinishedGoingToSleep")
+ }
+
+ fun logNotifyStartedWakingUp() {
+ logBuffer.log(TAG, DEBUG, "notifyStartedWakingUp")
+ }
+
+ fun logDoKeyguardShowingLockScreen() {
+ logBuffer.log(TAG, DEBUG, "doKeyguard: showing the lock screen")
+ }
+
+ fun logDoKeyguardNotShowingLockScreenOff() {
+ logBuffer.log(TAG, DEBUG, "doKeyguard: not showing because lockscreen is off")
+ }
+
+ fun logDoKeyguardNotShowingDeviceNotProvisioned() {
+ logBuffer.log(TAG, DEBUG, "doKeyguard: not showing because device isn't " +
+ "provisioned and the sim is not locked or missing")
+ }
+
+ fun logDoKeyguardNotShowingAlreadyShowing() {
+ logBuffer.log(TAG, DEBUG, "doKeyguard: not showing because it is already showing")
+ }
+
+ fun logDoKeyguardNotShowingBootingCryptkeeper() {
+ logBuffer.log(TAG, DEBUG, "doKeyguard: not showing because booting to cryptkeeper")
+ }
+
+ fun logDoKeyguardNotShowingExternallyDisabled() {
+ logBuffer.log(TAG, DEBUG, "doKeyguard: not showing because externally disabled")
+ }
+
+ fun logFailedToCallOnDeviceProvisioned(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onDeviceProvisioned",
+ remoteException
+ )
+ }
+
+ fun logMaybeHandlePendingLockNotHandling() {
+ logBuffer.log(TAG, DEBUG, "#maybeHandlePendingLock: not handling because the " +
+ "screen off animation's isKeyguardShowDelayed() returned true. This should be " +
+ "handled soon by #onStartedWakingUp, or by the end actions of the " +
+ "screen off animation.")
+ }
+
+ fun logMaybeHandlePendingLockKeyguardGoingAway() {
+ logBuffer.log(TAG, DEBUG, "#maybeHandlePendingLock: not handling because the " +
+ "keyguard is going away. This should be handled shortly by " +
+ "StatusBar#finishKeyguardFadingAway.")
+ }
+
+ fun logMaybeHandlePendingLockHandling() {
+ logBuffer.log(TAG, DEBUG, "#maybeHandlePendingLock: handling pending lock; " +
+ "locking keyguard.")
+ }
+
+ fun logSetAlarmToTurnOffKeyguard(delayedShowingSequence: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = delayedShowingSequence },
+ { "setting alarm to turn off keyguard, seq = $int1" }
+ )
+ }
+
+ fun logOnStartedWakingUp(delayedShowingSequence: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = delayedShowingSequence },
+ { "onStartedWakingUp, seq = $int1" }
+ )
+ }
+
+ fun logSetKeyguardEnabled(enabled: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = enabled },
+ { "setKeyguardEnabled($bool1)" }
+ )
+ }
+
+ fun logIgnoreVerifyUnlockRequest() {
+ logBuffer.log(TAG, DEBUG, "in process of verifyUnlock request, ignoring")
+ }
+
+ fun logRememberToReshowLater() {
+ logBuffer.log(TAG, DEBUG, "remembering to reshow, hiding keyguard, disabling " +
+ "status bar expansion")
+ }
+
+ fun logPreviouslyHiddenReshow() {
+ logBuffer.log(TAG, DEBUG, "previously hidden, reshowing, reenabling status " +
+ "bar expansion")
+ }
+
+ fun logOnKeyguardExitResultFalseResetting() {
+ logBuffer.log(TAG, DEBUG, "onKeyguardExitResult(false), resetting")
+ }
+
+ fun logWaitingUntilKeyguardVisibleIsFalse() {
+ logBuffer.log(TAG, DEBUG, "waiting until mWaitingUntilKeyguardVisible is false")
+ }
+
+ fun logDoneWaitingUntilKeyguardVisible() {
+ logBuffer.log(TAG, DEBUG, "done waiting for mWaitingUntilKeyguardVisible")
+ }
+
+ fun logUnoccludeAnimatorOnAnimationStart() {
+ logBuffer.log(TAG, DEBUG, "UnoccludeAnimator#onAnimationStart. " +
+ "Set occluded = false.")
+ }
+
+ fun logNoAppsProvidedToUnoccludeRunner() {
+ logBuffer.log(TAG, DEBUG, "No apps provided to unocclude runner; " +
+ "skipping animation and unoccluding.")
+ }
+
+ fun logReceivedDelayedKeyguardAction(sequence: Int, delayedShowingSequence: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = sequence
+ int2 = delayedShowingSequence
+ },
+ {
+ "received DELAYED_KEYGUARD_ACTION with seq = $int1 " +
+ "mDelayedShowingSequence = $int2"
+ }
+ )
+ }
+
+ fun logTimeoutWhileActivityDrawn() {
+ logBuffer.log(TAG, WARNING, "Timeout while waiting for activity drawn")
+ }
+
+ fun logTryKeyguardDonePending(
+ keyguardDonePending: Boolean,
+ hideAnimationRun: Boolean,
+ hideAnimationRunning: Boolean
+ ) {
+ logBuffer.log(TAG, DEBUG,
+ {
+ bool1 = keyguardDonePending
+ bool2 = hideAnimationRun
+ bool3 = hideAnimationRunning
+ },
+ { "tryKeyguardDone: pending - $bool1, animRan - $bool2 animRunning - $bool3" }
+ )
+ }
+
+ fun logTryKeyguardDonePreHideAnimation() {
+ logBuffer.log(TAG, DEBUG, "tryKeyguardDone: starting pre-hide animation")
+ }
+
+ fun logHandleKeyguardDone() {
+ logBuffer.log(TAG, DEBUG, "handleKeyguardDone")
+ }
+
+ fun logDeviceGoingToSleep() {
+ logBuffer.log(TAG, INFO, "Device is going to sleep, aborting keyguardDone")
+ }
+
+ fun logFailedToCallOnKeyguardExitResultTrue(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onKeyguardExitResult(true)",
+ remoteException
+ )
+ }
+
+ fun logHandleKeyguardDoneDrawing() {
+ logBuffer.log(TAG, DEBUG, "handleKeyguardDoneDrawing")
+ }
+
+ fun logHandleKeyguardDoneDrawingNotifyingKeyguardVisible() {
+ logBuffer.log(TAG, DEBUG, "handleKeyguardDoneDrawing: notifying " +
+ "mWaitingUntilKeyguardVisible")
+ }
+
+ fun logUpdateActivityLockScreenState(showing: Boolean, aodShowing: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = showing
+ bool2 = aodShowing
+ },
+ { "updateActivityLockScreenState($bool1, $bool2)" }
+ )
+ }
+
+ fun logFailedToCallSetLockScreenShown(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call setLockScreenShown",
+ remoteException
+ )
+ }
+
+ fun logKeyguardGoingAway() {
+ logBuffer.log(TAG, DEBUG, "keyguardGoingAway")
+ }
+
+ fun logFailedToCallKeyguardGoingAway(keyguardFlag: Int, remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ ERROR,
+ { int1 = keyguardFlag },
+ { "Failed to call keyguardGoingAway($int1)" },
+ remoteException
+ )
+ }
+
+ fun logHideAnimationFinishedRunnable() {
+ logBuffer.log(TAG, WARNING, "mHideAnimationFinishedRunnable#run")
+ }
+
+ fun logFailedToCallOnAnimationFinished(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onAnimationFinished",
+ remoteException
+ )
+ }
+
+ fun logFailedToCallOnAnimationStart(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onAnimationStart",
+ remoteException
+ )
+ }
+
+ fun logOnKeyguardExitRemoteAnimationFinished() {
+ logBuffer.log(TAG, DEBUG, "onKeyguardExitRemoteAnimationFinished")
+ }
+
+ fun logSkipOnKeyguardExitRemoteAnimationFinished(
+ cancelled: Boolean,
+ surfaceBehindRemoteAnimationRunning: Boolean,
+ surfaceBehindRemoteAnimationRequested: Boolean
+ ) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = cancelled
+ bool2 = surfaceBehindRemoteAnimationRunning
+ bool3 = surfaceBehindRemoteAnimationRequested
+ },
+ {
+ "skip onKeyguardExitRemoteAnimationFinished cancelled=$bool1 " +
+ "surfaceAnimationRunning=$bool2 " +
+ "surfaceAnimationRequested=$bool3"
+ }
+ )
+ }
+
+ fun logOnKeyguardExitRemoteAnimationFinishedHideKeyguardView() {
+ logBuffer.log(TAG, DEBUG, "onKeyguardExitRemoteAnimationFinished" +
+ "#hideKeyguardViewAfterRemoteAnimation")
+ }
+
+ fun logSkipHideKeyguardViewAfterRemoteAnimation(
+ dismissingFromSwipe: Boolean,
+ wasShowing: Boolean
+ ) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = dismissingFromSwipe
+ bool2 = wasShowing
+ },
+ {
+ "skip hideKeyguardViewAfterRemoteAnimation dismissFromSwipe=$bool1 " +
+ "wasShowing=$bool2"
+ }
+ )
+ }
+
+ fun logCouldNotGetStatusBarManager() {
+ logBuffer.log(TAG, WARNING, "Could not get status bar manager")
+ }
+
+ fun logAdjustStatusBarLocked(
+ showing: Boolean,
+ occluded: Boolean,
+ secure: Boolean,
+ forceHideHomeRecentsButtons: Boolean,
+ flags: String
+ ) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = showing
+ bool2 = occluded
+ bool3 = secure
+ bool4 = forceHideHomeRecentsButtons
+ str3 = flags
+ },
+ {
+ "adjustStatusBarLocked: mShowing=$bool1 mOccluded=$bool2 isSecure=$bool3 " +
+ "force=$bool4 --> flags=0x$str3"
+ }
+ )
+ }
+
+ fun logFailedToCallOnShowingStateChanged(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call onShowingStateChanged",
+ remoteException
+ )
+ }
+
+ fun logFailedToCallNotifyTrustedChangedLocked(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call notifyTrustedChangedLocked",
+ remoteException
+ )
+ }
+
+ fun logFailedToCallIKeyguardStateCallback(remoteException: RemoteException) {
+ logBuffer.log(
+ TAG,
+ WARNING,
+ "Failed to call to IKeyguardStateCallback",
+ remoteException
+ )
+ }
+
+ fun logOccludeAnimatorOnAnimationStart() {
+ logBuffer.log(TAG, DEBUG, "OccludeAnimator#onAnimationStart. Set occluded = true.")
+ }
+
+ fun logOccludeAnimationCancelledByWm(isKeyguardOccluded: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = isKeyguardOccluded },
+ { "Occlude animation cancelled by WM. Setting occluded state to: $bool1" }
+ )
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 589ec0e72b3b..9b5f54a0a91d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -92,7 +92,7 @@ open class AuthBiometricFingerprintIconController(
STATE_ERROR -> true
STATE_AUTHENTICATING_ANIMATING_IN,
STATE_AUTHENTICATING -> oldState == STATE_ERROR || oldState == STATE_HELP
- STATE_AUTHENTICATED -> false
+ STATE_AUTHENTICATED -> true
else -> false
}
@@ -114,7 +114,13 @@ open class AuthBiometricFingerprintIconController(
R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
}
}
- STATE_AUTHENTICATED -> R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
+ STATE_AUTHENTICATED -> {
+ if (oldState == STATE_ERROR || oldState == STATE_HELP) {
+ R.raw.fingerprint_dialogue_error_to_success_lottie
+ } else {
+ R.raw.fingerprint_dialogue_fingerprint_to_success_lottie
+ }
+ }
else -> return null
}
return if (id != null) return id else null
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
index 31baa0ff1154..9cce066afe9d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
@@ -75,7 +75,7 @@ open class AuthBiometricFingerprintView(
}
}
- override fun getDelayAfterAuthenticatedDurationMs() = 0
+ override fun getDelayAfterAuthenticatedDurationMs() = 500
override fun getStateForAfterError() = STATE_AUTHENTICATING
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index e866b9c0bb25..fc5cf9f005ed 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -468,6 +468,7 @@ public abstract class AuthBiometricView extends LinearLayout {
break;
case STATE_AUTHENTICATED:
+ removePendingAnimations();
if (mSize != AuthDialog.SIZE_SMALL) {
mConfirmButton.setVisibility(View.GONE);
mNegativeButton.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 6dfbd426ef30..898959e6eb58 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -53,7 +53,6 @@ import android.os.IBinder;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.Log;
@@ -89,34 +88,6 @@ public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
- /**
- * Run Keyguard animation as remote animation in System UI instead of local animation in
- * the server process.
- *
- * 0: Runs all keyguard animation as local animation
- * 1: Only runs keyguard going away animation as remote animation
- * 2: Runs all keyguard animation as remote animation
- *
- * Note: Must be consistent with WindowManagerService.
- */
- private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
- "persist.wm.enable_remote_keyguard_animation";
-
- private static final int sEnableRemoteKeyguardAnimation =
- SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 2);
-
- /**
- * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
- */
- public static boolean sEnableRemoteKeyguardGoingAwayAnimation =
- sEnableRemoteKeyguardAnimation >= 1;
-
- /**
- * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
- */
- public static boolean sEnableRemoteKeyguardOccludeAnimation =
- sEnableRemoteKeyguardAnimation >= 2;
-
private final KeyguardViewMediator mKeyguardViewMediator;
private final KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
private final ShellTransitions mShellTransitions;
@@ -288,97 +259,90 @@ public class KeyguardService extends Service {
if (mShellTransitions == null || !Transitions.ENABLE_SHELL_TRANSITIONS) {
RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- if (sEnableRemoteKeyguardGoingAwayAnimation) {
- final RemoteAnimationAdapter exitAnimationAdapter =
- new RemoteAnimationAdapter(mExitAnimationRunner, 0, 0);
- definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
- exitAnimationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
- exitAnimationAdapter);
- }
- if (sEnableRemoteKeyguardOccludeAnimation) {
- final RemoteAnimationAdapter occludeAnimationAdapter =
- new RemoteAnimationAdapter(
- mKeyguardViewMediator.getOccludeAnimationRunner(), 0, 0);
- definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE,
- occludeAnimationAdapter);
-
- final RemoteAnimationAdapter unoccludeAnimationAdapter =
- new RemoteAnimationAdapter(
- mKeyguardViewMediator.getUnoccludeAnimationRunner(), 0, 0);
- definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE,
- unoccludeAnimationAdapter);
- }
+ final RemoteAnimationAdapter exitAnimationAdapter =
+ new RemoteAnimationAdapter(mExitAnimationRunner, 0, 0);
+ definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
+ exitAnimationAdapter);
+ definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+ exitAnimationAdapter);
+ final RemoteAnimationAdapter occludeAnimationAdapter =
+ new RemoteAnimationAdapter(
+ mKeyguardViewMediator.getOccludeAnimationRunner(), 0, 0);
+ definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE,
+ occludeAnimationAdapter);
+
+ final RemoteAnimationAdapter unoccludeAnimationAdapter =
+ new RemoteAnimationAdapter(
+ mKeyguardViewMediator.getUnoccludeAnimationRunner(), 0, 0);
+ definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE,
+ unoccludeAnimationAdapter);
ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay(
DEFAULT_DISPLAY, definition);
return;
}
- if (sEnableRemoteKeyguardGoingAwayAnimation) {
- Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_GOING_AWAY");
- TransitionFilter f = new TransitionFilter();
- f.mFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
- mShellTransitions.registerRemote(f,
- new RemoteTransition(wrap(mExitAnimationRunner), getIApplicationThread()));
- }
- if (sEnableRemoteKeyguardOccludeAnimation) {
- Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_(UN)OCCLUDE");
- // Register for occluding
- final RemoteTransition occludeTransition = new RemoteTransition(
- mOccludeAnimation, getIApplicationThread());
- TransitionFilter f = new TransitionFilter();
- f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
- f.mRequirements = new TransitionFilter.Requirement[]{
- new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
- // First require at-least one app showing that occludes.
- f.mRequirements[0].mMustBeIndependent = false;
- f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
- f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
- // Then require that we aren't closing any occludes (because this would mean a
- // regular task->task or activity->activity animation not involving keyguard).
- f.mRequirements[1].mNot = true;
- f.mRequirements[1].mMustBeIndependent = false;
- f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD;
- f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
- mShellTransitions.registerRemote(f, occludeTransition);
-
- // Now register for un-occlude.
- final RemoteTransition unoccludeTransition = new RemoteTransition(
- mUnoccludeAnimation, getIApplicationThread());
- f = new TransitionFilter();
- f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
- f.mRequirements = new TransitionFilter.Requirement[]{
- new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
- // First require at-least one app going-away (doesn't need occlude flag
- // as that is implicit by it having been visible and we don't want to exclude
- // cases where we are un-occluding because the app removed its showWhenLocked
- // capability at runtime).
- f.mRequirements[1].mMustBeIndependent = false;
- f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
- f.mRequirements[1].mMustBeTask = true;
- // Then require that we aren't opening any occludes (otherwise we'd remain
- // occluded).
- f.mRequirements[0].mNot = true;
- f.mRequirements[0].mMustBeIndependent = false;
- f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
- f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
- mShellTransitions.registerRemote(f, unoccludeTransition);
-
- // Register for specific transition type.
- // Above filter cannot fulfill all conditions.
- // E.g. close top activity while screen off but next activity is occluded, this should
- // an occluded transition, but since the activity is invisible, the condition would
- // match unoccluded transition.
- // But on the contrary, if we add above condition in occluded transition, then when user
- // trying to dismiss occluded activity when unlock keyguard, the condition would match
- // occluded transition.
- f = new TransitionFilter();
- f.mTypeSet = new int[]{TRANSIT_KEYGUARD_OCCLUDE};
- mShellTransitions.registerRemote(f, occludeTransition);
-
- f = new TransitionFilter();
- f.mTypeSet = new int[]{TRANSIT_KEYGUARD_UNOCCLUDE};
- mShellTransitions.registerRemote(f, unoccludeTransition);
- }
+ Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_GOING_AWAY");
+ TransitionFilter f = new TransitionFilter();
+ f.mFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
+ mShellTransitions.registerRemote(f,
+ new RemoteTransition(wrap(mExitAnimationRunner), getIApplicationThread()));
+
+ Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_(UN)OCCLUDE");
+ // Register for occluding
+ final RemoteTransition occludeTransition = new RemoteTransition(
+ mOccludeAnimation, getIApplicationThread());
+ f = new TransitionFilter();
+ f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
+ f.mRequirements = new TransitionFilter.Requirement[]{
+ new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
+ // First require at-least one app showing that occludes.
+ f.mRequirements[0].mMustBeIndependent = false;
+ f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
+ f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+ // Then require that we aren't closing any occludes (because this would mean a
+ // regular task->task or activity->activity animation not involving keyguard).
+ f.mRequirements[1].mNot = true;
+ f.mRequirements[1].mMustBeIndependent = false;
+ f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD;
+ f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+ mShellTransitions.registerRemote(f, occludeTransition);
+
+ // Now register for un-occlude.
+ final RemoteTransition unoccludeTransition = new RemoteTransition(
+ mUnoccludeAnimation, getIApplicationThread());
+ f = new TransitionFilter();
+ f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
+ f.mRequirements = new TransitionFilter.Requirement[]{
+ new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
+ // First require at-least one app going-away (doesn't need occlude flag
+ // as that is implicit by it having been visible and we don't want to exclude
+ // cases where we are un-occluding because the app removed its showWhenLocked
+ // capability at runtime).
+ f.mRequirements[1].mMustBeIndependent = false;
+ f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+ f.mRequirements[1].mMustBeTask = true;
+ // Then require that we aren't opening any occludes (otherwise we'd remain
+ // occluded).
+ f.mRequirements[0].mNot = true;
+ f.mRequirements[0].mMustBeIndependent = false;
+ f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
+ f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+ mShellTransitions.registerRemote(f, unoccludeTransition);
+
+ // Register for specific transition type.
+ // Above filter cannot fulfill all conditions.
+ // E.g. close top activity while screen off but next activity is occluded, this should
+ // an occluded transition, but since the activity is invisible, the condition would
+ // match unoccluded transition.
+ // But on the contrary, if we add above condition in occluded transition, then when user
+ // trying to dismiss occluded activity when unlock keyguard, the condition would match
+ // occluded transition.
+ f = new TransitionFilter();
+ f.mTypeSet = new int[]{TRANSIT_KEYGUARD_OCCLUDE};
+ mShellTransitions.registerRemote(f, occludeTransition);
+
+ f = new TransitionFilter();
+ f.mTypeSet = new int[]{TRANSIT_KEYGUARD_UNOCCLUDE};
+ mShellTransitions.registerRemote(f, unoccludeTransition);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index c944e509c5f1..9ecfb7521151 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -484,8 +484,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
// surface behind the keyguard to finish unlocking.
if (keyguardStateController.isFlingingToDismissKeyguard) {
playCannedUnlockAnimation()
- } else if (keyguardStateController.isDismissingFromSwipe
- && willUnlockWithInWindowLauncherAnimations) {
+ } else if (keyguardStateController.isDismissingFromSwipe &&
+ willUnlockWithInWindowLauncherAnimations) {
// If we're swiping to unlock to the Launcher, and can play in-window animations,
// make the launcher surface fully visible and play the in-window unlock animation
// on the launcher icons. System UI will remain locked, using the swipe-to-unlock
@@ -622,10 +622,6 @@ class KeyguardUnlockAnimationController @Inject constructor(
}
override fun onKeyguardDismissAmountChanged() {
- if (!willHandleUnlockAnimation()) {
- return
- }
-
if (keyguardViewController.isShowing && !playingCannedUnlockAnimation) {
showOrHideSurfaceIfDismissAmountThresholdsReached()
@@ -685,8 +681,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
*/
private fun finishKeyguardExitRemoteAnimationIfReachThreshold() {
// no-op if keyguard is not showing or animation is not enabled.
- if (!KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation ||
- !keyguardViewController.isShowing) {
+ if (!keyguardViewController.isShowing) {
return
}
@@ -727,8 +722,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
// If we're dismissing via swipe to the Launcher, we'll play in-window scale animations, so
// don't also scale the window.
- if (keyguardStateController.isDismissingFromSwipe
- && willUnlockWithInWindowLauncherAnimations) {
+ if (keyguardStateController.isDismissingFromSwipe &&
+ willUnlockWithInWindowLauncherAnimations) {
scaleFactor = 1f
}
@@ -920,17 +915,6 @@ class KeyguardUnlockAnimationController @Inject constructor(
}
/**
- * Whether this animation controller will be handling the unlock. We require remote animations
- * to be enabled to do this.
- *
- * If this is not true, nothing in this class is relevant, and the unlock will be handled in
- * [KeyguardViewMediator].
- */
- fun willHandleUnlockAnimation(): Boolean {
- return KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation
- }
-
- /**
* Whether the RemoteAnimation on the app/launcher surface behind the keyguard is 'running'.
*/
fun isAnimatingBetweenKeyguardAndSurfaceBehind(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4a7346ee2901..70e0d5fa9ba7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -73,8 +73,6 @@ import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.EventLog;
-import android.util.Log;
-import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.IRemoteAnimationFinishedCallback;
@@ -106,6 +104,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.logging.KeyguardViewMediatorLogger;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.CoreStartable;
import com.android.systemui.DejankUtils;
@@ -513,8 +512,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
public void onKeyguardVisibilityChanged(boolean showing) {
synchronized (KeyguardViewMediator.this) {
if (!showing && mPendingPinLock) {
- Log.i(TAG, "PIN lock requested, starting keyguard");
-
+ mLogger.logPinLockRequestedStartingKeyguard();
// Bring the keyguard back in order to show the PIN lock
mPendingPinLock = false;
doKeyguardLocked(null);
@@ -524,7 +522,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void onUserSwitching(int userId) {
- if (DEBUG) Log.d(TAG, String.format("onUserSwitching %d", userId));
+ mLogger.logUserSwitching(userId);
// Note that the mLockPatternUtils user has already been updated from setCurrentUser.
// We need to force a reset of the views, since lockNow (called by
// ActivityManagerService) will not reconstruct the keyguard if it is already showing.
@@ -542,7 +540,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void onUserSwitchComplete(int userId) {
- if (DEBUG) Log.d(TAG, String.format("onUserSwitchComplete %d", userId));
+ mLogger.logOnUserSwitchComplete(userId);
if (userId != UserHandle.USER_SYSTEM) {
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
// Don't try to dismiss if the user has Pin/Pattern/Password set
@@ -570,8 +568,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
public void onSimStateChanged(int subId, int slotId, int simState) {
if (DEBUG_SIM_STATES) {
- Log.d(TAG, "onSimStateChanged(subId=" + subId + ", slotId=" + slotId
- + ",state=" + simState + ")");
+ mLogger.logOnSimStateChanged(subId, slotId, String.valueOf(simState));
}
int size = mKeyguardStateCallbacks.size();
@@ -580,7 +577,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
mKeyguardStateCallbacks.get(i).onSimSecureStateChanged(simPinSecure);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onSimSecureStateChanged", e);
+ mLogger.logFailedToCallOnSimSecureStateChanged(e);
if (e instanceof DeadObjectException) {
mKeyguardStateCallbacks.remove(i);
}
@@ -603,9 +600,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
synchronized (KeyguardViewMediator.this) {
if (shouldWaitForProvisioning()) {
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing,"
- + " we need to show the keyguard since the "
- + "device isn't provisioned yet.");
+ if (DEBUG_SIM_STATES) {
+ mLogger.logIccAbsentIsNotShowing();
+ }
doKeyguardLocked(null);
} else {
resetStateLocked();
@@ -615,8 +612,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// MVNO SIMs can become transiently NOT_READY when switching networks,
// so we should only lock when they are ABSENT.
if (lastSimStateWasLocked) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to ABSENT when the "
- + "previous state was locked. Reset the state.");
+ if (DEBUG_SIM_STATES) {
+ mLogger.logSimMovedToAbsent();
+ }
resetStateLocked();
}
mSimWasLocked.append(slotId, false);
@@ -629,9 +627,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mSimWasLocked.append(slotId, true);
mPendingPinLock = true;
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG,
- "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
- + "showing; need to show keyguard so user can enter sim pin");
+ if (DEBUG_SIM_STATES) {
+ mLogger.logIntentValueIccLocked();
+ }
doKeyguardLocked(null);
} else {
resetStateLocked();
@@ -641,29 +639,36 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
case TelephonyManager.SIM_STATE_PERM_DISABLED:
synchronized (KeyguardViewMediator.this) {
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED and "
- + "keygaurd isn't showing.");
+ if (DEBUG_SIM_STATES) {
+ mLogger.logPermDisabledKeyguardNotShowing();
+ }
doKeyguardLocked(null);
} else {
- if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
- + "show permanently disabled message in lockscreen.");
+ if (DEBUG_SIM_STATES) {
+ mLogger.logPermDisabledResetStateLocked();
+ }
resetStateLocked();
}
}
break;
case TelephonyManager.SIM_STATE_READY:
synchronized (KeyguardViewMediator.this) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing);
+ if (DEBUG_SIM_STATES) {
+ mLogger.logReadyResetState(mShowing);
+ }
if (mShowing && mSimWasLocked.get(slotId, false)) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to READY when the "
- + "previously was locked. Reset the state.");
+ if (DEBUG_SIM_STATES) {
+ mLogger.logSimMovedToReady();
+ }
mSimWasLocked.append(slotId, false);
resetStateLocked();
}
}
break;
default:
- if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
+ if (DEBUG_SIM_STATES) {
+ mLogger.logUnspecifiedSimState(simState);
+ }
break;
}
}
@@ -708,7 +713,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
if (targetUserId != ActivityManager.getCurrentUser()) {
return;
}
- if (DEBUG) Log.d(TAG, "keyguardDone");
+ mLogger.logKeyguardDone();
tryKeyguardDone();
}
@@ -727,7 +732,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void keyguardDonePending(boolean strongAuth, int targetUserId) {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardDonePending");
- if (DEBUG) Log.d(TAG, "keyguardDonePending");
+ mLogger.logKeyguardDonePending();
if (targetUserId != ActivityManager.getCurrentUser()) {
Trace.endSection();
return;
@@ -746,7 +751,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void keyguardGone() {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardGone");
- if (DEBUG) Log.d(TAG, "keyguardGone");
+ mLogger.logKeyguardGone();
mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false);
mKeyguardDisplayManager.hide();
Trace.endSection();
@@ -832,8 +837,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void onLaunchAnimationCancelled() {
- Log.d(TAG, "Occlude launch animation cancelled. Occluded state is now: "
- + mOccluded);
+ mLogger.logOccludeLaunchAnimationCancelled(mOccluded);
}
@Override
@@ -853,8 +857,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void setLaunchContainer(@NonNull ViewGroup launchContainer) {
// No-op, launch container is always the shade.
- Log.wtf(TAG, "Someone tried to change the launch container for the "
- + "ActivityLaunchAnimator, which should never happen.");
+ mLogger.logActivityLaunchAnimatorLaunchContainerChanged();
}
@NonNull
@@ -905,8 +908,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */);
- Log.d(TAG, "Unocclude animation cancelled. Occluded state is now: "
- + mOccluded);
+ mLogger.logUnoccludeAnimationCancelled(mOccluded);
}
@Override
@@ -914,12 +916,11 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
- Log.d(TAG, "UnoccludeAnimator#onAnimationStart. Set occluded = false.");
+ mLogger.logUnoccludeAnimatorOnAnimationStart();
setOccluded(false /* isOccluded */, true /* animate */);
if (apps == null || apps.length == 0 || apps[0] == null) {
- Log.d(TAG, "No apps provided to unocclude runner; "
- + "skipping animation and unoccluding.");
+ mLogger.logNoAppsProvidedToUnoccludeRunner();
finishedCallback.onAnimationFinished();
return;
}
@@ -1007,6 +1008,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private ScreenOnCoordinator mScreenOnCoordinator;
private Lazy<ActivityLaunchAnimator> mActivityLaunchAnimator;
+ private KeyguardViewMediatorLogger mLogger;
/**
* Injected constructor. See {@link KeyguardModule}.
@@ -1035,7 +1037,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
InteractionJankMonitor interactionJankMonitor,
DreamOverlayStateController dreamOverlayStateController,
Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
- Lazy<ActivityLaunchAnimator> activityLaunchAnimator) {
+ Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
+ KeyguardViewMediatorLogger logger) {
super(context);
mFalsingCollector = falsingCollector;
mLockPatternUtils = lockPatternUtils;
@@ -1078,6 +1081,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mDreamOverlayStateController = dreamOverlayStateController;
mActivityLaunchAnimator = activityLaunchAnimator;
+ mLogger = logger;
mPowerButtonY = context.getResources().getDimensionPixelSize(
R.dimen.physical_power_button_center_screen_location_y);
@@ -1141,21 +1145,21 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mLockSoundId = mLockSounds.load(soundPath, 1);
}
if (soundPath == null || mLockSoundId == 0) {
- Log.w(TAG, "failed to load lock sound from " + soundPath);
+ mLogger.logFailedLoadLockSound(soundPath);
}
soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
if (soundPath != null) {
mUnlockSoundId = mLockSounds.load(soundPath, 1);
}
if (soundPath == null || mUnlockSoundId == 0) {
- Log.w(TAG, "failed to load unlock sound from " + soundPath);
+ mLogger.logFailedLoadUnlockSound(soundPath);
}
soundPath = Settings.Global.getString(cr, Settings.Global.TRUSTED_SOUND);
if (soundPath != null) {
mTrustedSoundId = mLockSounds.load(soundPath, 1);
}
if (soundPath == null || mTrustedSoundId == 0) {
- Log.w(TAG, "failed to load trusted sound from " + soundPath);
+ mLogger.logFailedLoadTrustedSound(soundPath);
}
int lockSoundDefaultAttenuation = mContext.getResources().getInteger(
@@ -1184,7 +1188,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void handleSystemReady() {
synchronized (this) {
- if (DEBUG) Log.d(TAG, "onSystemReady");
+ mLogger.logOnSystemReady();
mSystemReady = true;
doKeyguardLocked(null);
mUpdateMonitor.registerCallback(mUpdateCallback);
@@ -1202,7 +1206,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
* {@link WindowManagerPolicyConstants#OFF_BECAUSE_OF_TIMEOUT}.
*/
public void onStartedGoingToSleep(@WindowManagerPolicyConstants.OffReason int offReason) {
- if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + offReason + ")");
+ mLogger.logOnStartedGoingToSleep(offReason);
synchronized (this) {
mDeviceInteractive = false;
mPowerGestureIntercepted = false;
@@ -1218,11 +1222,11 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
long timeout = getLockTimeout(KeyguardUpdateMonitor.getCurrentUser());
mLockLater = false;
if (mExitSecureCallback != null) {
- if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
+ mLogger.logPendingExitSecureCallbackCancelled();
try {
mExitSecureCallback.onKeyguardExitResult(false);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedOnKeyguardExitResultFalse(e);
}
mExitSecureCallback = null;
if (!mExternallyEnabled) {
@@ -1267,7 +1271,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
public void onFinishedGoingToSleep(
@WindowManagerPolicyConstants.OffReason int offReason, boolean cameraGestureTriggered) {
- if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + offReason + ")");
+ mLogger.logOnFinishedGoingToSleep(offReason);
synchronized (this) {
mDeviceInteractive = false;
mGoingToSleep = false;
@@ -1325,13 +1329,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// - The screen off animation is cancelled by the device waking back up. We will call
// maybeHandlePendingLock from KeyguardViewMediator#onStartedWakingUp.
if (mScreenOffAnimationController.isKeyguardShowDelayed()) {
- if (DEBUG) {
- Log.d(TAG, "#maybeHandlePendingLock: not handling because the screen off "
- + "animation's isKeyguardShowDelayed() returned true. This should be "
- + "handled soon by #onStartedWakingUp, or by the end actions of the "
- + "screen off animation.");
- }
-
+ mLogger.logMaybeHandlePendingLockNotHandling();
return;
}
@@ -1341,18 +1339,11 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// StatusBar#finishKeyguardFadingAway, which is always responsible for setting
// isKeyguardGoingAway to false.
if (mKeyguardStateController.isKeyguardGoingAway()) {
- if (DEBUG) {
- Log.d(TAG, "#maybeHandlePendingLock: not handling because the keyguard is "
- + "going away. This should be handled shortly by "
- + "StatusBar#finishKeyguardFadingAway.");
- }
-
+ mLogger.logMaybeHandlePendingLockKeyguardGoingAway();
return;
}
- if (DEBUG) {
- Log.d(TAG, "#maybeHandlePendingLock: handling pending lock; locking keyguard.");
- }
+ mLogger.logMaybeHandlePendingLockHandling();
doKeyguardLocked(null);
setPendingLock(false);
@@ -1421,8 +1412,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
PendingIntent sender = PendingIntent.getBroadcast(mContext,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
- if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
- + mDelayedShowingSequence);
+ mLogger.logSetAlarmToTurnOffKeyguard(mDelayedShowingSequence);
doKeyguardLaterForChildProfilesLocked();
}
@@ -1482,7 +1472,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mAnimatingScreenOff = false;
cancelDoKeyguardLaterLocked();
cancelDoKeyguardForChildProfilesLocked();
- if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence);
+ mLogger.logOnStartedWakingUp(mDelayedShowingSequence);
notifyStartedWakingUp();
}
mUpdateMonitor.dispatchStartedWakingUp();
@@ -1542,37 +1532,35 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
public void setKeyguardEnabled(boolean enabled) {
synchronized (this) {
- if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
+ mLogger.logSetKeyguardEnabled(enabled);
mExternallyEnabled = enabled;
if (!enabled && mShowing) {
if (mExitSecureCallback != null) {
- if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
+ mLogger.logIgnoreVerifyUnlockRequest();
// we're in the process of handling a request to verify the user
// can get past the keyguard. ignore extraneous requests to disable / re-enable
return;
}
// hiding keyguard that is showing, remember to reshow later
- if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
- + "disabling status bar expansion");
+ mLogger.logRememberToReshowLater();
mNeedToReshowWhenReenabled = true;
updateInputRestrictedLocked();
hideLocked();
} else if (enabled && mNeedToReshowWhenReenabled) {
// re-enabled after previously hidden, reshow
- if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
- + "status bar expansion");
+ mLogger.logPreviouslyHiddenReshow();
mNeedToReshowWhenReenabled = false;
updateInputRestrictedLocked();
if (mExitSecureCallback != null) {
- if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
+ mLogger.logOnKeyguardExitResultFalseResetting();
try {
mExitSecureCallback.onKeyguardExitResult(false);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedToCallOnKeyguardExitResultFalse(e);
}
mExitSecureCallback = null;
resetStateLocked();
@@ -1584,7 +1572,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// and causing an ANR).
mWaitingUntilKeyguardVisible = true;
mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
- if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
+ mLogger.logWaitingUntilKeyguardVisibleIsFalse();
while (mWaitingUntilKeyguardVisible) {
try {
wait();
@@ -1592,7 +1580,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
Thread.currentThread().interrupt();
}
}
- if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
+ mLogger.logDoneWaitingUntilKeyguardVisible();
}
}
}
@@ -1604,31 +1592,31 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
public void verifyUnlock(IKeyguardExitCallback callback) {
Trace.beginSection("KeyguardViewMediator#verifyUnlock");
synchronized (this) {
- if (DEBUG) Log.d(TAG, "verifyUnlock");
+ mLogger.logVerifyUnlock();
if (shouldWaitForProvisioning()) {
// don't allow this api when the device isn't provisioned
- if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
+ mLogger.logIgnoreUnlockDeviceNotProvisioned();
try {
callback.onKeyguardExitResult(false);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedToCallOnKeyguardExitResultFalse(e);
}
} else if (mExternallyEnabled) {
// this only applies when the user has externally disabled the
// keyguard. this is unexpected and means the user is not
// using the api properly.
- Log.w(TAG, "verifyUnlock called when not externally disabled");
+ mLogger.logVerifyUnlockCalledNotExternallyDisabled();
try {
callback.onKeyguardExitResult(false);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedToCallOnKeyguardExitResultFalse(e);
}
} else if (mExitSecureCallback != null) {
// already in progress with someone else
try {
callback.onKeyguardExitResult(false);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedToCallOnKeyguardExitResultFalse(e);
}
} else if (!isSecure()) {
@@ -1640,7 +1628,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
callback.onKeyguardExitResult(true);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedToCallOnKeyguardExitResultFalse(e);
}
} else {
@@ -1649,7 +1637,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
callback.onKeyguardExitResult(false);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ mLogger.logFailedToCallOnKeyguardExitResultFalse(e);
}
}
}
@@ -1667,10 +1655,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
* Notify us when the keyguard is occluded by another window
*/
public void setOccluded(boolean isOccluded, boolean animate) {
- Log.d(TAG, "setOccluded(" + isOccluded + ")");
-
Trace.beginSection("KeyguardViewMediator#setOccluded");
- if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
+ mLogger.logSetOccluded(isOccluded);
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_TRANSITION_FROM_AOD);
mHandler.removeMessages(SET_OCCLUDED);
Message msg = mHandler.obtainMessage(SET_OCCLUDED, isOccluded ? 1 : 0, animate ? 1 : 0);
@@ -1699,7 +1685,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private void handleSetOccluded(boolean isOccluded, boolean animate) {
Trace.beginSection("KeyguardViewMediator#handleSetOccluded");
- Log.d(TAG, "handleSetOccluded(" + isOccluded + ")");
+ mLogger.logHandleSetOccluded(isOccluded);
synchronized (KeyguardViewMediator.this) {
if (mHiding && isOccluded) {
// We're in the process of going away but WindowManager wants to show a
@@ -1756,7 +1742,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
callback.onInputRestrictedStateChanged(inputRestricted);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
+ mLogger.logFailedToCallOnDeviceProvisioned(e);
if (e instanceof DeadObjectException) {
mKeyguardStateCallbacks.remove(callback);
}
@@ -1771,8 +1757,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void doKeyguardLocked(Bundle options) {
// if another app is disabling us, don't show
if (!mExternallyEnabled) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
-
+ mLogger.logDoKeyguardNotShowingExternallyDisabled();
mNeedToReshowWhenReenabled = true;
return;
}
@@ -1781,7 +1766,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// to account for the hiding animation which results in a delay and discrepancy
// between flags
if (mShowing && mKeyguardViewControllerLazy.get().isShowing()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+ mLogger.logDoKeyguardNotShowingAlreadyShowing();
resetStateLocked();
return;
}
@@ -1800,20 +1785,19 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
|| ((absent || disabled) && requireSim);
if (!lockedOrMissing && shouldWaitForProvisioning()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
- + " and the sim is not locked or missing");
+ mLogger.logDoKeyguardNotShowingDeviceNotProvisioned();
return;
}
boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
&& !lockedOrMissing && !forceShow) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+ mLogger.logDoKeyguardNotShowingLockScreenOff();
return;
}
}
- if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
+ mLogger.logDoKeyguardShowingLockScreen();
showLocked(options);
}
@@ -1851,32 +1835,23 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
* @see #handleReset
*/
private void resetStateLocked() {
- if (DEBUG) Log.e(TAG, "resetStateLocked");
+ mLogger.logResetStateLocked();
Message msg = mHandler.obtainMessage(RESET);
mHandler.sendMessage(msg);
}
- /**
- * Send message to keyguard telling it to verify unlock
- * @see #handleVerifyUnlock()
- */
- private void verifyUnlockLocked() {
- if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
- mHandler.sendEmptyMessage(VERIFY_UNLOCK);
- }
-
private void notifyStartedGoingToSleep() {
- if (DEBUG) Log.d(TAG, "notifyStartedGoingToSleep");
+ mLogger.logNotifyStartedGoingToSleep();
mHandler.sendEmptyMessage(NOTIFY_STARTED_GOING_TO_SLEEP);
}
private void notifyFinishedGoingToSleep() {
- if (DEBUG) Log.d(TAG, "notifyFinishedGoingToSleep");
+ mLogger.logNotifyFinishedGoingToSleep();
mHandler.sendEmptyMessage(NOTIFY_FINISHED_GOING_TO_SLEEP);
}
private void notifyStartedWakingUp() {
- if (DEBUG) Log.d(TAG, "notifyStartedWakingUp");
+ mLogger.logNotifyStartedWakingUp();
mHandler.sendEmptyMessage(NOTIFY_STARTED_WAKING_UP);
}
@@ -1886,7 +1861,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private void showLocked(Bundle options) {
Trace.beginSection("KeyguardViewMediator#showLocked acquiring mShowKeyguardWakeLock");
- if (DEBUG) Log.d(TAG, "showLocked");
+ mLogger.logShowLocked();
// ensure we stay awake until we are finished displaying the keyguard
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options);
@@ -1903,7 +1878,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private void hideLocked() {
Trace.beginSection("KeyguardViewMediator#hideLocked");
- if (DEBUG) Log.d(TAG, "hideLocked");
+ mLogger.logHideLocked();
Message msg = mHandler.obtainMessage(HIDE);
mHandler.sendMessage(msg);
Trace.endSection();
@@ -1982,8 +1957,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
public void onReceive(Context context, Intent intent) {
if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
final int sequence = intent.getIntExtra("seq", 0);
- if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
- + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
+ mLogger.logReceivedDelayedKeyguardAction(sequence, mDelayedShowingSequence);
synchronized (KeyguardViewMediator.this) {
if (mDelayedShowingSequence == sequence) {
doKeyguardLocked(null);
@@ -2016,7 +1990,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void keyguardDone() {
Trace.beginSection("KeyguardViewMediator#keyguardDone");
- if (DEBUG) Log.d(TAG, "keyguardDone()");
+ mLogger.logKeyguardDone();
userActivity();
EventLog.writeEvent(70000, 2);
Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
@@ -2108,7 +2082,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
case KEYGUARD_DONE_PENDING_TIMEOUT:
Trace.beginSection("KeyguardViewMediator#handleMessage"
+ " KEYGUARD_DONE_PENDING_TIMEOUT");
- Log.w(TAG, "Timeout while waiting for activity drawn!");
+ mLogger.logTimeoutWhileActivityDrawn();
Trace.endSection();
break;
case SYSTEM_READY:
@@ -2119,14 +2093,15 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
};
private void tryKeyguardDone() {
- if (DEBUG) {
- Log.d(TAG, "tryKeyguardDone: pending - " + mKeyguardDonePending + ", animRan - "
- + mHideAnimationRun + " animRunning - " + mHideAnimationRunning);
- }
+ mLogger.logTryKeyguardDonePending(
+ mKeyguardDonePending,
+ mHideAnimationRun,
+ mHideAnimationRunning
+ );
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
handleKeyguardDone();
} else if (!mHideAnimationRun) {
- if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
+ mLogger.logTryKeyguardDonePreHideAnimation();
mHideAnimationRun = true;
mHideAnimationRunning = true;
mKeyguardViewControllerLazy.get()
@@ -2146,14 +2121,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
}
});
- if (DEBUG) Log.d(TAG, "handleKeyguardDone");
+ mLogger.logHandleKeyguardDone();
synchronized (this) {
resetKeyguardDonePendingLocked();
}
if (mGoingToSleep) {
mUpdateMonitor.clearBiometricRecognizedWhenKeyguardDone(currentUser);
- Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
+ mLogger.logDeviceGoingToSleep();
return;
}
setPendingLock(false); // user may have authenticated during the screen off animation
@@ -2161,7 +2136,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
mExitSecureCallback.onKeyguardExitResult(true /* authenciated */);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult()", e);
+ mLogger.logFailedToCallOnKeyguardExitResultTrue(e);
}
mExitSecureCallback = null;
@@ -2204,9 +2179,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void handleKeyguardDoneDrawing() {
Trace.beginSection("KeyguardViewMediator#handleKeyguardDoneDrawing");
synchronized(this) {
- if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing");
+ mLogger.logHandleKeyguardDoneDrawing();
if (mWaitingUntilKeyguardVisible) {
- if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
+ mLogger.logHandleKeyguardDoneDrawingNotifyingKeyguardVisible();
mWaitingUntilKeyguardVisible = false;
notifyAll();
@@ -2256,12 +2231,11 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void updateActivityLockScreenState(boolean showing, boolean aodShowing) {
mUiBgExecutor.execute(() -> {
- if (DEBUG) {
- Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
- }
+ mLogger.logUpdateActivityLockScreenState(showing, aodShowing);
try {
ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing);
} catch (RemoteException e) {
+ mLogger.logFailedToCallSetLockScreenShown(e);
}
});
}
@@ -2278,10 +2252,10 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
synchronized (KeyguardViewMediator.this) {
if (!mSystemReady) {
- if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
+ mLogger.logIgnoreHandleShow();
return;
} else {
- if (DEBUG) Log.d(TAG, "handleShow");
+ mLogger.logHandleShow();
}
mHiding = false;
@@ -2313,7 +2287,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Override
public void run() {
Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable");
- if (DEBUG) Log.d(TAG, "keyguardGoingAway");
+ mLogger.logKeyguardGoingAway();
mKeyguardViewControllerLazy.get().keyguardGoingAway();
int flags = 0;
@@ -2357,7 +2331,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
} catch (RemoteException e) {
- Log.e(TAG, "Error while calling WindowManager", e);
+ mLogger.logFailedToCallKeyguardGoingAway(keyguardFlag, e);
}
});
Trace.endSection();
@@ -2365,7 +2339,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
};
private final Runnable mHideAnimationFinishedRunnable = () -> {
- Log.e(TAG, "mHideAnimationFinishedRunnable#run");
+ mLogger.logHideAnimationFinishedRunnable();
mHideAnimationRunning = false;
tryKeyguardDone();
};
@@ -2385,14 +2359,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleHide");
+ mLogger.logHandleHide();
if (mustNotUnlockCurrentUser()) {
// In split system user mode, we never unlock system user. The end user has to
// switch to another user.
// TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
// still completes and makes the screen blank.
- if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
+ mLogger.logSplitSystemUserQuitUnlocking();
mKeyguardExitAnimationRunner = null;
return;
}
@@ -2424,8 +2398,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) {
Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");
- Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
- + " fadeoutDuration=" + fadeoutDuration);
+ mLogger.logHandleStartKeyguardExitAnimation(startTime, fadeoutDuration);
synchronized (KeyguardViewMediator.this) {
// Tell ActivityManager that we canceled the keyguard animation if
@@ -2441,7 +2414,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onAnimationFinished", e);
+ mLogger.logFailedToCallOnAnimationFinished(e);
}
}
setShowingLocked(mShowing, true /* force */);
@@ -2454,7 +2427,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
LatencyTracker.getInstance(mContext)
.onActionEnd(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
- if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation && runner != null
+ if (runner != null
&& finishedCallback != null) {
// Wrap finishedCallback to clean up the keyguard state once the animation is done.
IRemoteAnimationFinishedCallback callback =
@@ -2464,7 +2437,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onAnimationFinished", e);
+ mLogger.logFailedToCallOnAnimationFinished(e);
}
onKeyguardExitFinished();
mKeyguardViewControllerLazy.get().hide(0 /* startTime */,
@@ -2483,13 +2456,12 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
runner.onAnimationStart(WindowManager.TRANSIT_KEYGUARD_GOING_AWAY, apps,
wallpapers, nonApps, callback);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onAnimationStart", e);
+ mLogger.logFailedToCallOnAnimationStart(e);
}
// When remaining on the shade, there's no need to do a fancy remote animation,
// it will dismiss the panel in that case.
- } else if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation
- && !mStatusBarStateController.leaveOpenOnKeyguardHide()
+ } else if (!mStatusBarStateController.leaveOpenOnKeyguardHide()
&& apps != null && apps.length > 0) {
mSurfaceBehindRemoteAnimationFinishedCallback = finishedCallback;
mSurfaceBehindRemoteAnimationRunning = true;
@@ -2548,7 +2520,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
- Slog.e(TAG, "RemoteException");
+ mLogger.logFailedToCallOnAnimationFinished(e);
} finally {
mInteractionJankMonitor.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
@@ -2559,7 +2531,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
- Slog.e(TAG, "RemoteException");
+ mLogger.logFailedToCallOnAnimationFinished(e);
} finally {
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
@@ -2628,11 +2600,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
* @param cancelled {@code true} if the animation was cancelled before it finishes.
*/
public void onKeyguardExitRemoteAnimationFinished(boolean cancelled) {
- Log.d(TAG, "onKeyguardExitRemoteAnimationFinished");
+ mLogger.logOnKeyguardExitRemoteAnimationFinished();
if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) {
- Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled
- + " surfaceAnimationRunning=" + mSurfaceBehindRemoteAnimationRunning
- + " surfaceAnimationRequested=" + mSurfaceBehindRemoteAnimationRequested);
+ mLogger.logSkipOnKeyguardExitRemoteAnimationFinished(cancelled, false, false);
return;
}
@@ -2646,13 +2616,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
onKeyguardExitFinished();
if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) {
- Log.d(TAG, "onKeyguardExitRemoteAnimationFinished"
- + "#hideKeyguardViewAfterRemoteAnimation");
+ mLogger.logOnKeyguardExitRemoteAnimationFinishedHideKeyguardView();
mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation();
} else {
- Log.d(TAG, "skip hideKeyguardViewAfterRemoteAnimation"
- + " dismissFromSwipe=" + mKeyguardStateController.isDismissingFromSwipe()
- + " wasShowing=" + wasShowing);
+ mLogger.logSkipHideKeyguardViewAfterRemoteAnimation(
+ mKeyguardStateController.isDismissingFromSwipe(),
+ wasShowing
+ );
}
finishSurfaceBehindRemoteAnimation(cancelled);
@@ -2749,7 +2719,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
if (mStatusBarManager == null) {
- Log.w(TAG, "Could not get status bar manager");
+ mLogger.logCouldNotGetStatusBarManager();
} else {
// Disable aspects of the system/status/navigation bars that must not be re-enabled by
// windows that appear on top, ever
@@ -2767,12 +2737,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
flags |= StatusBarManager.DISABLE_RECENT;
}
-
- if (DEBUG) {
- Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded
- + " isSecure=" + isSecure() + " force=" + forceHideHomeRecentsButtons
- + " --> flags=0x" + Integer.toHexString(flags));
- }
+ mLogger.logAdjustStatusBarLocked(
+ mShowing,
+ mOccluded,
+ isSecure(),
+ forceHideHomeRecentsButtons,
+ Integer.toHexString(flags)
+ );
mStatusBarManager.disable(flags);
}
@@ -2784,7 +2755,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private void handleReset() {
synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleReset");
+ mLogger.logHandleReset();
mKeyguardViewControllerLazy.get().reset(true /* hideBouncerWhenShowing */);
}
}
@@ -2796,7 +2767,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void handleVerifyUnlock() {
Trace.beginSection("KeyguardViewMediator#handleVerifyUnlock");
synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
+ mLogger.logHandleVerifyUnlock();
setShowingLocked(true);
mKeyguardViewControllerLazy.get().dismissAndCollapse();
}
@@ -2805,7 +2776,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void handleNotifyStartedGoingToSleep() {
synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleNotifyStartedGoingToSleep");
+ mLogger.logHandleNotifyStartedGoingToSleep();
mKeyguardViewControllerLazy.get().onStartedGoingToSleep();
}
}
@@ -2816,7 +2787,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private void handleNotifyFinishedGoingToSleep() {
synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleNotifyFinishedGoingToSleep");
+ mLogger.logHandleNotifyFinishedGoingToSleep();
mKeyguardViewControllerLazy.get().onFinishedGoingToSleep();
}
}
@@ -2824,7 +2795,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private void handleNotifyStartedWakingUp() {
Trace.beginSection("KeyguardViewMediator#handleMotifyStartedWakingUp");
synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleNotifyWakingUp");
+ mLogger.logHandleNotifyWakingUp();
mKeyguardViewControllerLazy.get().onStartedWakingUp();
}
Trace.endSection();
@@ -3090,7 +3061,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
callback.onShowingStateChanged(showing, KeyguardUpdateMonitor.getCurrentUser());
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onShowingStateChanged", e);
+ mLogger.logFailedToCallOnShowingStateChanged(e);
if (e instanceof DeadObjectException) {
mKeyguardStateCallbacks.remove(callback);
}
@@ -3109,7 +3080,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
try {
mKeyguardStateCallbacks.get(i).onTrustedChanged(trusted);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call notifyTrustedChangedLocked", e);
+ mLogger.logFailedToCallNotifyTrustedChangedLocked(e);
if (e instanceof DeadObjectException) {
mKeyguardStateCallbacks.remove(i);
}
@@ -3132,7 +3103,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
callback.onTrustedChanged(mUpdateMonitor.getUserHasTrust(
KeyguardUpdateMonitor.getCurrentUser()));
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call to IKeyguardStateCallback", e);
+ mLogger.logFailedToCallIKeyguardStateCallback(e);
}
}
}
@@ -3209,7 +3180,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// internal state to reflect that immediately, vs. waiting for the launch animator to
// begin. Otherwise, calls to setShowingLocked, etc. will not know that we're about to
// be occluded and might re-show the keyguard.
- Log.d(TAG, "OccludeAnimator#onAnimationStart. Set occluded = true.");
+ mLogger.logOccludeAnimatorOnAnimationStart();
setOccluded(true /* isOccluded */, false /* animate */);
}
@@ -3217,8 +3188,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
super.onAnimationCancelled(isKeyguardOccluded);
- Log.d(TAG, "Occlude animation cancelled by WM. "
- + "Setting occluded state to: " + isKeyguardOccluded);
+ mLogger.logOccludeAnimationCancelledByWm(isKeyguardOccluded);
setOccluded(isKeyguardOccluded /* occluded */, false /* animate */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 56f1ac46a875..fdea62dc0cbe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -30,6 +30,7 @@ import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
+import com.android.keyguard.logging.KeyguardViewMediatorLogger;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -105,7 +106,8 @@ public class KeyguardModule {
InteractionJankMonitor interactionJankMonitor,
DreamOverlayStateController dreamOverlayStateController,
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
- Lazy<ActivityLaunchAnimator> activityLaunchAnimator) {
+ Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
+ KeyguardViewMediatorLogger logger) {
return new KeyguardViewMediator(
context,
falsingCollector,
@@ -132,7 +134,8 @@ public class KeyguardModule {
interactionJankMonitor,
dreamOverlayStateController,
notificationShadeWindowController,
- activityLaunchAnimator);
+ activityLaunchAnimator,
+ logger);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
index 6124e10144f2..77ad8069f273 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
@@ -158,8 +158,13 @@ class LogBuffer @JvmOverloads constructor(
* add more detail to every log may do more to improve overall logging than adding more logs
* with this method.
*/
- fun log(tag: String, level: LogLevel, @CompileTimeConstant message: String) =
- log(tag, level, {str1 = message}, { str1!! })
+ fun log(
+ tag: String,
+ level: LogLevel,
+ @CompileTimeConstant message: String,
+ exception: Throwable? = null
+ ) =
+ log(tag, level, {str1 = message}, { str1!! }, exception)
/**
* You should call [log] instead of this method.
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt
index 323ee21953ea..684839f2b124 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt
@@ -1,4 +1,7 @@
package com.android.systemui.log.dagger
+import javax.inject.Qualifier
+
/** A [com.android.systemui.log.LogBuffer] for KeyguardUpdateMonitor. */
+@Qualifier
annotation class KeyguardUpdateMonitorLog
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardViewMediatorLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardViewMediatorLog.kt
new file mode 100644
index 000000000000..88e227b8ae35
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardViewMediatorLog.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.log.dagger
+
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for KeyguardViewMediator. */
+@Qualifier
+annotation class KeyguardViewMediatorLog \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index c2a87649adef..9af42f825e00 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -305,4 +305,15 @@ public class LogModule {
public static LogBuffer provideKeyguardUpdateMonitorLogBuffer(LogBufferFactory factory) {
return factory.create("KeyguardUpdateMonitorLog", 200);
}
+
+ /**
+ * Provides a {@link LogBuffer} for use by
+ * {@link com.android.systemui.keyguard.KeyguardViewMediator}.
+ */
+ @Provides
+ @SysUISingleton
+ @KeyguardViewMediatorLog
+ public static LogBuffer provideKeyguardViewMediatorLogBuffer(LogBufferFactory factory) {
+ return factory.create("KeyguardViewMediatorLog", 100);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index e754d5db4186..33c1f99c6f4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -477,15 +477,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
if (!wasDeviceInteractive) {
mPendingShowBouncer = true;
} else {
- // If the keyguard unlock controller is going to handle the unlock animation, it
- // will fling the panel collapsed when it's ready.
- if (!mKeyguardUnlockAnimationController.willHandleUnlockAnimation()) {
- mShadeController.animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_NONE,
- true /* force */,
- false /* delayed */,
- BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
- }
mPendingShowBouncer = false;
mKeyguardViewController.notifyKeyguardAuthenticated(
false /* strongAuth */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index e444e0a1e2c5..a1904859cd4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -152,7 +152,6 @@ import com.android.systemui.flags.Flags;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
-import com.android.systemui.keyguard.KeyguardService;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -1875,11 +1874,9 @@ public class CentralSurfacesImpl extends CoreStartable implements
return true;
}
- // If we are locked and have to dismiss the keyguard, only animate if remote unlock
- // animations are enabled. We also don't animate non-activity launches as they can break the
- // animation.
+ // We don't animate non-activity launches as they can break the animation.
// TODO(b/184121838): Support non activity launches on the lockscreen.
- return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
+ return isActivityIntent;
}
/** Whether we should animate an activity launch. */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
index 328ad39cddd5..58d906907488 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
@@ -41,11 +41,13 @@ import org.mockito.junit.MockitoJUnit
@SmallTest
class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
- @JvmField @Rule
+ @JvmField
+ @Rule
var mockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var callback: AuthBiometricView.Callback
+
@Mock
private lateinit var panelController: AuthPanelController
@@ -67,6 +69,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
fun fingerprintSuccessDoesNotRequireExplicitConfirmation() {
biometricView.onDialogAnimatedIn()
biometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticated).isTrue()
@@ -86,6 +89,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
// icon acts as confirm button
biometricView.mIconView.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticated).isTrue()
@@ -102,6 +106,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
verify(callback, never()).onAction(AuthBiometricView.Callback.ACTION_ERROR)
biometricView.onError(TYPE_FINGERPRINT, "that's a nope")
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
index 687cb517b2f4..bce98cf116d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
@@ -42,20 +42,23 @@ import org.mockito.junit.MockitoJUnit
@SmallTest
class AuthBiometricFingerprintViewTest : SysuiTestCase() {
- @JvmField @Rule
+ @JvmField
+ @Rule
val mockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var callback: AuthBiometricView.Callback
+
@Mock
private lateinit var panelController: AuthPanelController
private lateinit var biometricView: AuthBiometricView
private fun createView(allowDeviceCredential: Boolean = false): AuthBiometricFingerprintView {
- val view = R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView(
+ val view: AuthBiometricFingerprintView =
+ R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView(
mContext, callback, panelController, allowDeviceCredential = allowDeviceCredential
- ) as AuthBiometricFingerprintView
+ )
waitForIdleSync()
return view
}
@@ -73,6 +76,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
@Test
fun testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() {
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticated).isTrue()
@@ -83,6 +87,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
fun testOnAuthenticationSucceeded_confirmationRequired_updatesDialogContents() {
biometricView.setRequireConfirmation(true)
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
// TODO: this should be tested in the subclasses
@@ -104,6 +109,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
@Test
fun testPositiveButton_sendsActionAuthenticated() {
biometricView.mConfirmButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED)
@@ -114,6 +120,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
fun testNegativeButton_beforeAuthentication_sendsActionButtonNegative() {
biometricView.onDialogAnimatedIn()
biometricView.mNegativeButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE)
@@ -126,6 +133,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
assertThat(biometricView.mNegativeButton.visibility).isEqualTo(View.GONE)
biometricView.mCancelButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_USER_CANCELED)
@@ -134,6 +142,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
@Test
fun testTryAgainButton_sendsActionTryAgain() {
biometricView.mTryAgainButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN)
@@ -144,6 +153,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
@Test
fun testOnErrorSendsActionError() {
biometricView.onError(BiometricAuthenticator.TYPE_FACE, "testError")
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR))
@@ -156,6 +166,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
val message = "another error"
biometricView.onError(BiometricAuthenticator.TYPE_FACE, message)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticating).isFalse()
@@ -178,6 +189,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
val view = View(mContext)
biometricView.setBackgroundView(view)
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
+ waitForIdleSync()
view.performClick()
verify(callback, never())
@@ -225,14 +237,14 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
biometricView.onSaveState(state)
assertThat(biometricView.mTryAgainButton.visibility).isEqualTo(View.GONE)
assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY))
- .isEqualTo(View.GONE)
+ .isEqualTo(View.GONE)
assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_STATE))
- .isEqualTo(AuthBiometricView.STATE_ERROR)
+ .isEqualTo(AuthBiometricView.STATE_ERROR)
assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE)
assertThat(state.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)).isTrue()
assertThat(biometricView.mIndicatorView.text).isEqualTo(failureMessage)
assertThat(state.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING))
- .isEqualTo(failureMessage)
+ .isEqualTo(failureMessage)
// TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 21c018a0419d..6e89bb90e558 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -48,6 +48,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardDisplayManager;
import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.logging.KeyguardViewMediatorLogger;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -106,6 +107,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy;
private @Mock DreamOverlayStateController mDreamOverlayStateController;
private @Mock ActivityLaunchAnimator mActivityLaunchAnimator;
+ private @Mock KeyguardViewMediatorLogger mLogger;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -262,7 +264,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mInteractionJankMonitor,
mDreamOverlayStateController,
mNotificationShadeWindowControllerLazy,
- () -> mActivityLaunchAnimator);
+ () -> mActivityLaunchAnimator,
+ mLogger);
mViewMediator.start();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
index 56aff3c2fc8b..7b12eb75e841 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
@@ -41,6 +41,18 @@ class LogBufferTest : SysuiTestCase() {
}
@Test
+ fun log_shouldSaveLogToBufferWithException() {
+ val exception = createTestException("Some exception test message", "SomeExceptionTestClass")
+ buffer.log("Test", LogLevel.INFO, "Some test message", exception)
+
+ val dumpedString = dumpBuffer()
+
+ assertThat(dumpedString).contains("Some test message")
+ assertThat(dumpedString).contains("Some exception test message")
+ assertThat(dumpedString).contains("SomeExceptionTestClass")
+ }
+
+ @Test
fun log_shouldRotateIfLogBufferIsFull() {
buffer.log("Test", LogLevel.INFO, "This should be rotated")
buffer.log("Test", LogLevel.INFO, "New test message")
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index b34482f0964f..3324c526ecc2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -354,16 +354,24 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
if (supportsFlagForNotImportantViews(info)) {
if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
- mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ mFetchFlags |=
+ AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
} else {
- mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ mFetchFlags &=
+ ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
}
}
if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
- mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
+ mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS;
} else {
- mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
+ mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS;
+ }
+
+ if (mAccessibilityServiceInfo.isAccessibilityTool()) {
+ mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
+ } else {
+ mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
}
mRequestTouchExplorationMode = (info.flags
@@ -1522,9 +1530,16 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
return false;
}
+ final boolean includeNotImportantViews = (mFetchFlags
+ & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0;
if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
&& !event.isImportantForAccessibility()
- && (mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
+ && !includeNotImportantViews) {
+ return false;
+ }
+
+ if (event.isAccessibilityDataPrivate()
+ && (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) {
return false;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6eabc981e9fe..6a6d2bb44d48 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3693,6 +3693,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ info.setAccessibilityTool(true);
final AccessibilityUserState userState;
synchronized (mLock) {
userState = getCurrentUserStateLocked();
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 265fbc510259..448d70c6b9a4 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -607,10 +607,8 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public void legacyDisassociate(String deviceMacAddress, String packageName, int userId) {
- if (DEBUG) {
- Log.i(TAG, "legacyDisassociate() pkg=u" + userId + "/" + packageName
- + ", macAddress=" + deviceMacAddress);
- }
+ Log.i(TAG, "legacyDisassociate() pkg=u" + userId + "/" + packageName
+ + ", macAddress=" + deviceMacAddress);
requireNonNull(deviceMacAddress);
requireNonNull(packageName);
@@ -622,7 +620,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public void disassociate(int associationId) {
- if (DEBUG) Log.i(TAG, "disassociate() associationId=" + associationId);
+ Log.i(TAG, "disassociate() associationId=" + associationId);
final AssociationInfo association =
getAssociationWithCallerChecks(associationId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 5cb25d36d94b..36908ce8c7b3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -49,10 +49,12 @@ import android.app.BroadcastOptions;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
+import android.app.IProcessObserver;
import android.app.IStopUserCallback;
import android.app.IUidObserver;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
+import android.app.ProcessStateEnum;
import android.app.ProfilerInfo;
import android.app.RemoteServiceException.CrashedByAdbException;
import android.app.UserSwitchObserver;
@@ -359,6 +361,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runSetBgRestrictionLevel(pw);
case "get-bg-restriction-level":
return runGetBgRestrictionLevel(pw);
+ case "observe-foreground-process":
+ return runGetCurrentForegroundProcess(pw, mInternal, mTaskInterface);
default:
return handleDefaultCommands(cmd);
}
@@ -3230,6 +3234,82 @@ final class ActivityManagerShellCommand extends ShellCommand {
return -1;
}
+ private int runGetCurrentForegroundProcess(PrintWriter pw,
+ IActivityManager iam, IActivityTaskManager iatm)
+ throws RemoteException {
+
+ ProcessObserver observer = new ProcessObserver(pw, iam, iatm, mInternal);
+ iam.registerProcessObserver(observer);
+
+ final InputStream mInput = getRawInputStream();
+ InputStreamReader converter = new InputStreamReader(mInput);
+ BufferedReader in = new BufferedReader(converter);
+ String line;
+ try {
+ while ((line = in.readLine()) != null) {
+ boolean addNewline = true;
+ if (line.length() <= 0) {
+ addNewline = false;
+ } else if ("q".equals(line) || "quit".equals(line)) {
+ break;
+ } else {
+ pw.println("Invalid command: " + line);
+ }
+ if (addNewline) {
+ pw.println("");
+ }
+ pw.flush();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ pw.flush();
+ } finally {
+ iam.unregisterProcessObserver(observer);
+ }
+ return 0;
+ }
+
+ static final class ProcessObserver extends IProcessObserver.Stub {
+
+ private PrintWriter mPw;
+ private IActivityManager mIam;
+ private IActivityTaskManager mIatm;
+ private ActivityManagerService mInternal;
+
+ ProcessObserver(PrintWriter mPw, IActivityManager mIam,
+ IActivityTaskManager mIatm, ActivityManagerService ams) {
+ this.mPw = mPw;
+ this.mIam = mIam;
+ this.mIatm = mIatm;
+ this.mInternal = ams;
+ }
+
+ @Override
+ public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
+ if (foregroundActivities) {
+ try {
+ int prcState = mIam.getUidProcessState(uid, "android");
+ int topPid = mInternal.getTopApp().getPid();
+ if (prcState == ProcessStateEnum.TOP && topPid == pid) {
+ mPw.println("New foreground process: " + pid);
+ }
+ mPw.flush();
+ } catch (RemoteException e) {
+ mPw.println("Error occurred in binder call");
+ mPw.flush();
+ }
+ }
+ }
+
+ @Override
+ public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
+ }
+
+ @Override
+ public void onProcessDied(int pid, int uid) {
+ }
+ }
+
private int runSetMemoryFactor(PrintWriter pw) throws RemoteException {
final String levelArg = getNextArgRequired();
@MemFactor int level = ADJ_MEM_FACTOR_NOTHING;
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 12aa66b84d85..de28be009c24 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -2566,16 +2565,10 @@ public class OomAdjuster {
case PROCESS_STATE_BOUND_TOP:
return PROCESS_CAPABILITY_NETWORK;
case PROCESS_STATE_FOREGROUND_SERVICE:
- if (psr.hasForegroundServices()) {
- // Capability from FGS are conditional depending on foreground service type in
- // manifest file and the mAllowWhileInUsePermissionInFgs flag.
- return PROCESS_CAPABILITY_NETWORK;
- } else {
- // process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client.
- // the implicit capability could be removed in the future, client should use
- // BIND_INCLUDE_CAPABILITY flag.
- return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK;
- }
+ // Capability from foreground service is conditional depending on
+ // foregroundServiceType in the manifest file and the
+ // mAllowWhileInUsePermissionInFgs flag.
+ return PROCESS_CAPABILITY_NETWORK;
case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
return PROCESS_CAPABILITY_NETWORK;
default:
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 134e2061c090..1302e226eba3 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -502,14 +502,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
GamePackageConfiguration(PackageManager packageManager, String packageName, int userId) {
mPackageName = packageName;
-
- // set flag default values
- mPerfModeOptedIn = false;
- mBatteryModeOptedIn = false;
- mAllowDownscale = true;
- mAllowAngle = true;
- mAllowFpsOverride = true;
-
try {
final ApplicationInfo ai = packageManager.getApplicationInfoAsUser(packageName,
PackageManager.GET_META_DATA, userId);
@@ -519,6 +511,12 @@ public final class GameManagerService extends IGameManagerService.Stub {
mBatteryModeOptedIn = ai.metaData.getBoolean(METADATA_BATTERY_MODE_ENABLE);
mAllowDownscale = ai.metaData.getBoolean(METADATA_WM_ALLOW_DOWNSCALE, true);
mAllowAngle = ai.metaData.getBoolean(METADATA_ANGLE_ALLOW_ANGLE, true);
+ } else {
+ mPerfModeOptedIn = false;
+ mBatteryModeOptedIn = false;
+ mAllowDownscale = true;
+ mAllowAngle = true;
+ mAllowFpsOverride = true;
}
}
} catch (NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 61e2419e2d14..9db9837ffc45 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -899,7 +899,7 @@ final class InstallPackageHelper {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
reconciledPackages = ReconcilePackageUtils.reconcilePackages(
reconcileRequest, mSharedLibraries,
- mPm.mSettings.getKeySetManagerService(), mPm.mSettings, mContext);
+ mPm.mSettings.getKeySetManagerService(), mPm.mSettings);
} catch (ReconcileFailure e) {
for (InstallRequest request : requests) {
request.mInstallResult.setError("Reconciliation failed...", e);
@@ -3669,7 +3669,7 @@ final class InstallPackageHelper {
final Map<String, ReconciledPackage> reconcileResult =
ReconcilePackageUtils.reconcilePackages(reconcileRequest,
mSharedLibraries, mPm.mSettings.getKeySetManagerService(),
- mPm.mSettings, mContext);
+ mPm.mSettings);
if ((scanFlags & SCAN_AS_APEX) == 0) {
appIdCreated = optimisticallyRegisterAppId(scanResult);
} else {
diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
index 3c4780171ee5..d6a133e43789 100644
--- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
+++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
@@ -16,7 +16,6 @@
package com.android.server.pm;
-import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
import static android.content.pm.SigningDetails.CapabilityMergeRule.MERGE_RESTRICTED_CAPABILITY;
@@ -24,31 +23,25 @@ import static android.content.pm.SigningDetails.CapabilityMergeRule.MERGE_RESTRI
import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
import static com.android.server.pm.PackageManagerService.SCAN_DONT_KILL_APP;
-import android.content.Context;
import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SigningDetails;
import android.os.SystemProperties;
-import android.permission.PermissionManager;
import android.util.ArrayMap;
import android.util.Log;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.pkg.component.ParsedUsesPermission;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.utils.WatchedLongSparseArray;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
final class ReconcilePackageUtils {
public static Map<String, ReconciledPackage> reconcilePackages(
final ReconcileRequest request, SharedLibrariesImpl sharedLibraries,
- KeySetManagerService ksms, Settings settings, Context context)
+ KeySetManagerService ksms, Settings settings)
throws ReconcileFailure {
final Map<String, ScanResult> scannedPackages = request.mScannedPackages;
@@ -168,43 +161,11 @@ final class ReconcilePackageUtils {
// over the latest parsed certs.
signingDetails = parsedPackage.getSigningDetails();
- // if this is a sharedUser, check to see if the new package is signed by a
- // newer signing certificate than the existing one, and if so, copy over the new
+ // if this is is a sharedUser, check to see if the new package is signed by a
+ // newer
+ // signing certificate than the existing one, and if so, copy over the new
// details
if (sharedUserSetting != null) {
- if (prepareResult != null && !prepareResult.mPackageToScan.isTestOnly()
- && sharedUserSetting.isPrivileged()
- && !signatureCheckPs.isSystem()) {
- final List<ParsedUsesPermission> usesPermissions =
- parsedPackage.getUsesPermissions();
- final List<String> usesPrivilegedPermissions = new ArrayList<>();
- final PermissionManager permissionManager = context.getSystemService(
- PermissionManager.class);
- // Check if the app requests any privileged permissions because that
- // violates the privapp-permissions allowlist check during boot.
- if (permissionManager != null) {
- for (int i = 0; i < usesPermissions.size(); i++) {
- final String permissionName = usesPermissions.get(i).getName();
- final PermissionInfo permissionInfo =
- permissionManager.getPermissionInfo(permissionName, 0);
- if (permissionInfo != null
- && (permissionInfo.getProtectionFlags()
- & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
- usesPrivilegedPermissions.add(permissionName);
- }
- }
- }
-
- if (!usesPrivilegedPermissions.isEmpty()) {
- throw new ReconcileFailure(INSTALL_FAILED_INVALID_APK,
- "Non-system package: " + parsedPackage.getPackageName()
- + " shares signature and sharedUserId with"
- + " a privileged package but requests"
- + " privileged permissions that are not"
- + " allowed: " + Arrays.toString(
- usesPrivilegedPermissions.toArray()));
- }
- }
// Attempt to merge the existing lineage for the shared SigningDetails with
// the lineage of the new package; if the shared SigningDetails are not
// returned this indicates the new package added new signers to the lineage
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 672c13c2dbf9..b31402cc935b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -54,6 +54,7 @@ import android.content.pm.ShortcutServiceInternal;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo.UserInfoFlag;
import android.content.pm.UserProperties;
+import android.content.pm.parsing.FrameworkParsingPackageUtils;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -5368,6 +5369,11 @@ public class UserManagerService extends IUserManager.Stub {
public void setApplicationRestrictions(String packageName, Bundle restrictions,
@UserIdInt int userId) {
checkSystemOrRoot("set application restrictions");
+ String validationResult =
+ FrameworkParsingPackageUtils.validateName(packageName, false, false);
+ if (validationResult != null) {
+ throw new IllegalArgumentException("Invalid package name: " + validationResult);
+ }
if (restrictions != null) {
restrictions.setDefusable(true);
}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
index f7a6eef29dee..d3a64bb0b9ac 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -62,6 +62,8 @@ public class PackageCacher {
StringBuilder sb = new StringBuilder(packageFile.getName());
sb.append('-');
sb.append(flags);
+ sb.append('-');
+ sb.append(packageFile.getAbsolutePath().hashCode());
return sb.toString();
}
@@ -171,7 +173,12 @@ public class PackageCacher {
}
final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
- return fromCacheEntry(bytes);
+ ParsedPackage parsed = fromCacheEntry(bytes);
+ if (!packageFile.getAbsolutePath().equals(parsed.getPath())) {
+ // Don't use this cache if the path doesn't match
+ return null;
+ }
+ return parsed;
} catch (Throwable e) {
Slog.w(TAG, "Error reading package cache: ", e);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 937a7891a849..1a1de0341aa0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -215,7 +215,6 @@ import com.android.server.wm.DisplayPolicy;
import com.android.server.wm.DisplayRotation;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
-import com.android.server.wm.WindowManagerService;
import java.io.File;
import java.io.FileNotFoundException;
@@ -2082,22 +2081,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
@Override
- public int onAppTransitionStartingLocked(boolean keyguardGoingAway,
- boolean keyguardOccluding, long duration, long statusBarAnimationStartTime,
+ public int onAppTransitionStartingLocked(long statusBarAnimationStartTime,
long statusBarAnimationDuration) {
- // When remote animation is enabled for KEYGUARD_GOING_AWAY transition, SysUI
- // receives IRemoteAnimationRunner#onAnimationStart to start animation, so we don't
- // need to call IKeyguardService#keyguardGoingAway here.
- return handleStartTransitionForKeyguardLw(keyguardGoingAway
- && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation,
- keyguardOccluding, duration);
+ return handleTransitionForKeyguardLw(false /* startKeyguardExitAnimation */,
+ false /* notifyOccluded */);
}
@Override
- public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
- handleStartTransitionForKeyguardLw(
- keyguardGoingAway, false /* keyguardOccludingStarted */,
- 0 /* duration */);
+ public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
+ // When KEYGUARD_GOING_AWAY app transition is canceled, we need to trigger relevant
+ // IKeyguardService calls to sync keyguard status in WindowManagerService and SysUI.
+ handleTransitionForKeyguardLw(
+ keyguardGoingAwayCancelled /* startKeyguardExitAnimation */,
+ true /* notifyOccluded */);
}
});
@@ -3262,31 +3258,39 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPendingKeyguardOccluded = occluded;
mKeyguardOccludedChanged = true;
} else {
- setKeyguardOccludedLw(occluded, false /* force */,
- false /* transitionStarted */);
+ setKeyguardOccludedLw(occluded, true /* notify */);
}
}
@Override
- public int applyKeyguardOcclusionChange(boolean transitionStarted) {
+ public int applyKeyguardOcclusionChange(boolean notify) {
if (mKeyguardOccludedChanged) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
+ mPendingKeyguardOccluded);
- if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */,
- transitionStarted)) {
+ if (setKeyguardOccludedLw(mPendingKeyguardOccluded, notify)) {
return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
}
}
return 0;
}
- private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway,
- boolean keyguardOccluding, long duration) {
- final int redoLayout = applyKeyguardOcclusionChange(keyguardOccluding);
+ /**
+ * Called when keyguard related app transition starts, or cancelled.
+ *
+ * @param startKeyguardExitAnimation Trigger IKeyguardService#startKeyguardExitAnimation to
+ * start keyguard exit animation.
+ * @param notifyOccluded Trigger IKeyguardService#setOccluded binder call to notify whether
+ * the top activity can occlude the keyguard or not.
+ *
+ * @return Whether the flags have changed and we have to redo the layout.
+ */
+ private int handleTransitionForKeyguardLw(boolean startKeyguardExitAnimation,
+ boolean notifyOccluded) {
+ final int redoLayout = applyKeyguardOcclusionChange(notifyOccluded);
if (redoLayout != 0) return redoLayout;
- if (keyguardGoingAway) {
+ if (startKeyguardExitAnimation) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
- startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration);
+ startKeyguardExitAnimation(SystemClock.uptimeMillis());
}
return 0;
}
@@ -3518,28 +3522,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* Updates the occluded state of the Keyguard.
*
* @param isOccluded Whether the Keyguard is occluded by another window.
- * @param force notify the occluded status to KeyguardService and update flags even though
- * occlude status doesn't change.
- * @param transitionStarted {@code true} if keyguard (un)occluded transition started.
+ * @param notify Notify keyguard occlude status change immediately via
+ * {@link com.android.internal.policy.IKeyguardService}.
* @return Whether the flags have changed and we have to redo the layout.
*/
- private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force,
- boolean transitionStarted) {
+ private boolean setKeyguardOccludedLw(boolean isOccluded, boolean notify) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
mKeyguardOccludedChanged = false;
- if (isKeyguardOccluded() == isOccluded && !force) {
+ if (isKeyguardOccluded() == isOccluded) {
return false;
}
-
- final boolean showing = mKeyguardDelegate.isShowing();
- final boolean animate = showing && !isOccluded;
- // When remote animation is enabled for keyguard (un)occlude transition, KeyguardService
- // uses remote animation start as a signal to update its occlusion status ,so we don't need
- // to notify here.
- final boolean notify = !WindowManagerService.sEnableRemoteKeyguardOccludeAnimation
- || !transitionStarted;
- mKeyguardDelegate.setOccluded(isOccluded, animate, notify);
- return showing;
+ mKeyguardDelegate.setOccluded(isOccluded, notify);
+ return mKeyguardDelegate.isShowing();
}
/** {@inheritDoc} */
@@ -4935,10 +4929,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
+ public void startKeyguardExitAnimation(long startTime) {
if (mKeyguardDelegate != null) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
- mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
+ mKeyguardDelegate.startKeyguardExitAnimation(startTime);
}
}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 4f00992c713e..2b0405073323 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -171,10 +171,10 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
void onKeyguardOccludedChangedLw(boolean occluded);
/**
- * Applies a keyguard occlusion change if one happened.
- * @param transitionStarted Whether keyguard (un)occlude transition is starting or not.
+ * @param notify {@code true} if the status change should be immediately notified via
+ * {@link com.android.internal.policy.IKeyguardService}
*/
- int applyKeyguardOcclusionChange(boolean transitionStarted);
+ int applyKeyguardOcclusionChange(boolean notify);
/**
* Interface to the Window Manager state associated with a particular
@@ -1129,11 +1129,10 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
/**
* Notifies the keyguard to start fading out.
+ * @param startTime the start time of the animation in uptime milliseconds
*
- * @param startTime the start time of the animation in uptime milliseconds
- * @param fadeoutDuration the duration of the exit animation, in milliseconds
*/
- void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+ void startKeyguardExitAnimation(long startTime);
/**
* Called when System UI has been started.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index b79ac6f68be2..7737421654ee 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -249,10 +249,10 @@ public class KeyguardServiceDelegate {
}
}
- public void setOccluded(boolean isOccluded, boolean animate, boolean notify) {
+ public void setOccluded(boolean isOccluded, boolean notify) {
if (mKeyguardService != null && notify) {
- if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
- mKeyguardService.setOccluded(isOccluded, animate);
+ if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ")");
+ mKeyguardService.setOccluded(isOccluded, false /* animate */);
}
mKeyguardState.occluded = isOccluded;
}
@@ -394,9 +394,9 @@ public class KeyguardServiceDelegate {
}
}
- public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
+ public void startKeyguardExitAnimation(long startTime) {
if (mKeyguardService != null) {
- mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration);
+ mKeyguardService.startKeyguardExitAnimation(startTime, 0);
}
}
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 fe4aa534df6f..df902c2916ba 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.addHistoryEventLocked(
+ mStats.recordHistoryEventLocked(
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 0c9ada8fa6db..968f9161b3c1 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -108,6 +108,7 @@ 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;
@@ -173,7 +174,6 @@ 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,6 +322,11 @@ 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;
@@ -413,7 +418,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (changed) {
final long uptimeMs = mClock.uptimeMillis();
final long elapsedRealtimeMs = mClock.elapsedRealtime();
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -668,16 +673,16 @@ public class BatteryStatsImpl extends BatteryStats {
/**
* Mapping isolated uids to the actual owning app uid.
*/
- final SparseIntArray mIsolatedUids = new SparseIntArray();
+ private final SparseIntArray mIsolatedUids = new SparseIntArray();
/**
* Internal reference count of isolated uids.
*/
- final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
+ private final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
/**
* The statistics we have collected organized by uids.
*/
- final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
+ private 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.
@@ -685,20 +690,21 @@ public class BatteryStatsImpl extends BatteryStats {
// changes.
@VisibleForTesting
protected ArrayList<StopwatchTimer> mPartialTimers = 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<>();
+ 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<>();
// Last partial timers we use for distributing CPU usage.
@VisibleForTesting
@@ -713,69 +719,24 @@ public class BatteryStatsImpl extends BatteryStats {
protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
private boolean mSystemReady;
- 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;
+ 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;
@NonNull
- 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 final BatteryStatsHistory mHistory;
private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
@@ -1391,7 +1352,6 @@ public class BatteryStatsImpl extends BatteryStats {
int mDischargeUnplugLevel;
int mDischargePlugLevel;
int mDischargeCurrentLevel;
- int mCurrentBatteryLevel;
int mLowDischargeAmountSinceCharge;
int mHighDischargeAmountSinceCharge;
int mDischargeScreenOnUnplugLevel;
@@ -1443,7 +1403,6 @@ public class BatteryStatsImpl extends BatteryStats {
private int mNumConnectivityChange;
- private int mBatteryVoltageMv = -1;
private int mEstimatedBatteryCapacityMah = -1;
private int mLastLearnedBatteryCapacityUah = -1;
@@ -1627,28 +1586,27 @@ public class BatteryStatsImpl extends BatteryStats {
}
public BatteryStatsImpl(Clock clock) {
- this(clock, (File) null);
+ this(clock, 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;
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
} else {
mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, historyDirectory,
- this::getMaxHistoryFiles);
+ mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES,
+ mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
}
- mHandler = null;
mPlatformIdleStateCallback = null;
mMeasuredEnergyRetriever = null;
mUserInfoProvider = null;
- mConstants = new Constants(mHandler);
- clearHistoryLocked();
}
private void init(Clock clock) {
@@ -3911,406 +3869,188 @@ public class BatteryStatsImpl extends BatteryStats {
return kmt;
}
- /**
- * 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;
- }
- }
-
- /*
- 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.
- */
+ private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator {
+ private final HistoryStepDetails mDetails = new HistoryStepDetails();
- @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;
- }
+ private boolean mHasHistoryStepDetails;
- final long deltaTime = cur.time - last.time;
- final int lastBatteryLevelInt = buildBatteryLevelInt(last);
- final int lastStateInt = buildStateInt(last);
+ private int mLastHistoryStepLevel;
- 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.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;
+ /**
+ * 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;
}
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
- + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
- + cur.eventTag.string);
- }
- if (computeStepDetails) {
+
+ // Perform a CPU update right after we do this collection, so we have started
+ // collecting good data for the next step.
+ requestImmediateCpuUpdate();
+
if (mPlatformIdleStateCallback != null) {
- mCurHistoryStepDetails.statSubsystemPowerState =
+ mDetails.statSubsystemPowerState =
mPlatformIdleStateCallback.getSubsystemLowPowerStats();
if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
- mCurHistoryStepDetails.statSubsystemPowerState);
-
- }
- 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;
+ 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();
} 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;
+ 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;
+ }
+
+ 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);
}
+ mCurStepCpuUserTimeMs += totalUTimeMs;
+ mCurStepCpuSystemTimeMs += totalSTimeMs;
+ mCurStepStatUserTimeMs += statUserTimeMs;
+ mCurStepStatSystemTimeMs += statSystemTimeMs;
+ mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
+ mCurStepStatIrqTimeMs += statIrqTimeMs;
+ mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
+ mCurStepStatIdleTimeMs += statIdleTimeMs;
+ }
+
+ @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;
}
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
}
@GuardedBy("this")
@Override
public void commitCurrentHistoryBatchLocked() {
- mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+ mHistory.commitCurrentHistoryBatchLocked();
}
@GuardedBy("this")
@@ -4326,191 +4066,9 @@ public class BatteryStatsImpl extends BatteryStats {
}
@GuardedBy("this")
- 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,
+ public void recordHistoryEventLocked(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;
- 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;
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
@GuardedBy("this")
@@ -4663,13 +4221,13 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(code, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
@GuardedBy("this")
public void noteCurrentTimeChangedLocked(long currentTimeMs,
long elapsedRealtimeMs, long uptimeMs) {
- recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
+ mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
}
@GuardedBy("this")
@@ -4686,7 +4244,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mRecordAllHistory) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
}
@GuardedBy("this")
@@ -4744,8 +4302,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mRecordAllHistory) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
- name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4761,7 +4318,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
}
@GuardedBy("this")
@@ -4777,8 +4334,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
- name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4794,7 +4350,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
}
@GuardedBy("this")
@@ -4812,7 +4368,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4860,7 +4416,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)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
@@ -4869,7 +4425,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)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4877,7 +4433,7 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4952,7 +4508,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++) {
- addHistoryEventLocked(mSecRealtime, mSecUptime,
+ mHistory.recordEvent(mSecRealtime, mSecUptime,
HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
}
}
@@ -4967,8 +4523,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++) {
- addHistoryEventLocked(mSecRealtime, mSecUptime,
- HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
+ mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
+ ent.getKey(), uids.keyAt(j));
}
}
}
@@ -5011,30 +4567,19 @@ public class BatteryStatsImpl extends BatteryStats {
if (mRecordAllHistory) {
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
mappedUid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
+ mHistory.recordEvent(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;
- 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;
+ mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
+ mappedUid);
+ } else if (!mWakeLockImportant && !unimportantForLogging) {
+ if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
+ mappedUid)) {
+ mWakeLockImportant = true;
+ }
}
mWakeLockNesting++;
}
@@ -5087,15 +4632,13 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
mappedUid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
}
}
if (mWakeLockNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WAKE_LOCK_FLAG);
}
}
if (mappedUid >= 0) {
@@ -5286,7 +4829,7 @@ public class BatteryStatsImpl extends BatteryStats {
mappedUid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
+ mHistory.recordEvent(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
@@ -5339,7 +4882,7 @@ public class BatteryStatsImpl extends BatteryStats {
mappedUid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
+ mHistory.recordEvent(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.
@@ -5361,15 +4904,10 @@ 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);
- mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
- mHistoryCur.wakeReasonTag.string = reason;
- mHistoryCur.wakeReasonTag.uid = 0;
+ mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
mLastWakeupReason = reason;
mLastWakeupUptimeMs = uptimeMs;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
@GuardedBy("this")
@@ -5380,22 +4918,11 @@ 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) {
- 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;
+ int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
+ int statSoftIrqTimeMs, int statIdleTimeMs) {
+ mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
+ statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
+ statSoftIrqTimeMs, statIdleTimeMs);
}
public void noteProcessDiedLocked(int uid, int pid) {
@@ -5425,10 +4952,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mSensorNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_SENSOR_ON_FLAG);
}
mSensorNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -5445,10 +4970,8 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
mSensorNesting--;
if (mSensorNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_SENSOR_ON_FLAG);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteStopSensor(sensor, elapsedRealtimeMs);
@@ -5498,10 +5021,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
final int mappedUid = mapUid(uid);
if (mGpsNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_GPS_ON_FLAG);
}
mGpsNesting++;
@@ -5526,10 +5047,8 @@ public class BatteryStatsImpl extends BatteryStats {
final int mappedUid = mapUid(uid);
mGpsNesting--;
if (mGpsNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_GPS_ON_FLAG);
stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
mGpsSignalQualityBin = -1;
}
@@ -5562,12 +5081,9 @@ public class BatteryStatsImpl extends BatteryStats {
if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
}
- mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
- | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
mGpsSignalQualityBin = signalLevel;
}
- return;
}
@GuardedBy("this")
@@ -5740,41 +5256,33 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
- boolean updateHistory = false;
+ int startStates = 0;
+ int stopStates = 0;
if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
- mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
+ startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
- updateHistory = true;
} else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
- mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
+ stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
- updateHistory = true;
}
if (Display.isOnState(state)) {
- mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
- + Integer.toHexString(mHistoryCur.states));
+ startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin]
.startRunningLocked(elapsedRealtimeMs);
}
- updateHistory = true;
} else if (Display.isOnState(oldState)) {
- mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
- + Integer.toHexString(mHistoryCur.states));
+ stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin]
.stopRunningLocked(elapsedRealtimeMs);
}
- updateHistory = true;
}
- if (updateHistory) {
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
- + Display.stateToString(state));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ if (startStates != 0 || stopStates != 0) {
+ mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
+ stopStates);
}
// Per screen state Cpu stats needed. Prepare to schedule an external sync.
@@ -5888,13 +5396,7 @@ public class BatteryStatsImpl extends BatteryStats {
long uptimeMs) {
if (mScreenBrightnessBin != overallBin) {
if (overallBin >= 0) {
- 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);
+ mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
}
if (mScreenState == Display.STATE_ON) {
if (mScreenBrightnessBin >= 0) {
@@ -5921,8 +5423,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWakeUpLocked(String reason, int reasonUid,
long elapsedRealtimeMs, long uptimeMs) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
- reason, reasonUid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
+ reasonUid);
}
@GuardedBy("this")
@@ -5941,7 +5443,7 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteConnectivityChangedLocked(int type, String extra,
long elapsedRealtimeMs, long uptimeMs) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
extra, type);
mNumConnectivityChange++;
}
@@ -5950,7 +5452,7 @@ public class BatteryStatsImpl extends BatteryStats {
private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
- addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
+ mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
}
@@ -5976,7 +5478,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
- mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
} else {
realElapsedRealtimeMs = timestampNs / (1000*1000);
long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
@@ -5988,11 +5491,9 @@ public class BatteryStatsImpl extends BatteryStats {
mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
- realElapsedRealtimeMs);
}
- mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ 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.
@@ -6042,17 +5543,14 @@ public class BatteryStatsImpl extends BatteryStats {
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
mPowerSaveModeEnabled = enabled;
if (enabled) {
- mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
- + Integer.toHexString(mHistoryCur.states2));
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_POWER_SAVE_FLAG);
mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
- + Integer.toHexString(mHistoryCur.states2));
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_POWER_SAVE_FLAG);
mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
}
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
enabled
? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
@@ -6076,7 +5574,7 @@ public class BatteryStatsImpl extends BatteryStats {
nowLightIdling = true;
}
if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
activeReason, activeUid);
}
if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
@@ -6106,11 +5604,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
if (mDeviceIdleMode != 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);
+ mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
mLastIdleTimeStartMs = elapsedRealtimeMs;
if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
@@ -6138,7 +5632,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.
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
pkgName, (int)versionCode);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
@@ -6150,8 +5644,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePackageUninstalledLocked(String pkgName,
long elapsedRealtimeMs, long uptimeMs) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
- HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
+ pkgName, 0);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
pc.mUpdate = true;
@@ -6180,10 +5674,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mPhoneOn) {
- mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
mPhoneOn = true;
mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -6192,10 +5684,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mPhoneOn) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
mPhoneOn = false;
mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
@@ -6233,11 +5723,12 @@ public class BatteryStatsImpl extends BatteryStats {
if (mUsbDataState != newState) {
mUsbDataState = newState;
if (connected) {
- mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_USB_DATA_LINK_FLAG);
} else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_USB_DATA_LINK_FLAG);
}
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -6258,6 +5749,10 @@ 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;
@@ -6286,10 +5781,8 @@ public class BatteryStatsImpl extends BatteryStats {
scanning = true;
strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (!mPhoneSignalScanningTimer.isRunningLocked()) {
- mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
+ addStateFlag = 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);
@@ -6299,9 +5792,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!scanning) {
// If we are no longer scanning, then stop the scanning timer.
if (mPhoneSignalScanningTimer.isRunningLocked()) {
- mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
- + Integer.toHexString(mHistoryCur.states));
+ removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
newHistory = true;
mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
@@ -6310,10 +5801,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (mPhoneServiceState != 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));
+ newState = state;
newHistory = true;
mPhoneServiceState = state;
}
@@ -6327,11 +5815,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- 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));
+ newSignalStrength = strengthBin;
newHistory = true;
FrameworkStatsLog.write(
FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
@@ -6342,7 +5826,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (newHistory) {
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
+ addStateFlag, removeStateFlag, newState, newSignalStrength);
}
}
@@ -6466,11 +5951,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != 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);
+ mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
if (mPhoneDataConnectionType >= 0) {
mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
elapsedRealtimeMs);
@@ -6543,10 +6024,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mWifiOn) {
- mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_ON_FLAG);
mWifiOn = true;
mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
@@ -6556,10 +6035,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mWifiOn) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_ON_FLAG);
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
@@ -6570,10 +6047,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mAudioOnNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_AUDIO_ON_FLAG);
mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mAudioOnNesting++;
@@ -6588,10 +6063,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mAudioOnNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_AUDIO_ON_FLAG);
mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6602,10 +6075,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mVideoOnNesting == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_VIDEO_ON_FLAG);
mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mVideoOnNesting++;
@@ -6620,10 +6091,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mVideoOnNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_VIDEO_ON_FLAG);
mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6634,10 +6103,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting > 0) {
mAudioOnNesting = 0;
- mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_AUDIO_ON_FLAG);
mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6650,10 +6117,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting > 0) {
mVideoOnNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_VIDEO_ON_FLAG);
mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6705,10 +6170,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mFlashlightOnNesting++ == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_FLASHLIGHT_FLAG);
mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6722,10 +6185,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mFlashlightOnNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_FLASHLIGHT_FLAG);
mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6736,10 +6197,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mCameraOnNesting++ == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CAMERA_FLAG);
mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6753,10 +6212,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (--mCameraOnNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CAMERA_FLAG);
mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6767,10 +6224,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting > 0) {
mCameraOnNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CAMERA_FLAG);
mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6783,10 +6238,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting > 0) {
mFlashlightOnNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_FLASHLIGHT_FLAG);
mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6803,10 +6256,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid = mapUid(uid);
if (mBluetoothScanNesting == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
}
mBluetoothScanNesting++;
@@ -6847,10 +6298,8 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
mBluetoothScanNesting--;
if (mBluetoothScanNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6885,10 +6334,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mBluetoothScanNesting > 0) {
mBluetoothScanNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6928,7 +6375,7 @@ public class BatteryStatsImpl extends BatteryStats {
private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
- addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
+ mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
}
@@ -6944,15 +6391,14 @@ public class BatteryStatsImpl extends BatteryStats {
if (uid > 0) {
noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
}
- mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ 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;
}
}
@@ -6960,10 +6406,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (!mGlobalWifiRunning) {
- mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_RUNNING_FLAG);
mGlobalWifiRunning = true;
mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
int N = ws.size();
@@ -7031,10 +6475,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_RUNNING_FLAG);
mGlobalWifiRunning = false;
mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
int N = ws.size();
@@ -7082,12 +6524,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
mWifiSupplState = supplState;
mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
- 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);
+ mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
}
}
@@ -7116,12 +6553,8 @@ public class BatteryStatsImpl extends BatteryStats {
if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- 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);
+ mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
+ strengthBin);
} else {
stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
}
@@ -7134,10 +6567,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiFullLockNesting == 0) {
- 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);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
}
mWifiFullLockNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -7148,10 +6579,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiFullLockNesting--;
if (mWifiFullLockNesting == 0) {
- 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);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
@@ -7167,10 +6596,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiScanNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_SCAN_FLAG);
}
mWifiScanNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -7186,10 +6613,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiScanNesting--;
if (mWifiScanNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_SCAN_FLAG);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteWifiScanStoppedLocked(elapsedRealtimeMs);
@@ -7214,14 +6639,10 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mWifiMulticastNesting == 0) {
- 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);
-
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
// Start Wifi Multicast overall timer
if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
- if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
}
}
@@ -7235,14 +6656,12 @@ public class BatteryStatsImpl extends BatteryStats {
uid = mapUid(uid);
mWifiMulticastNesting--;
if (mWifiMulticastNesting == 0) {
- 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);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
// Stop Wifi Multicast overall timer
if (mWifiMulticastWakelockTimer.isRunningLocked()) {
- if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
+ if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
@@ -7994,8 +7413,9 @@ 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.
- recordCurrentTimeChangeLocked(currentTimeMs, mClock.elapsedRealtime(),
- mClock.uptimeMillis());
+ mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
+ currentTimeMs
+ );
return currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
}
return mStartClockTimeMs;
@@ -11227,18 +10647,19 @@ public class BatteryStatsImpl extends BatteryStats {
UserInfoProvider userInfoProvider) {
init(clock);
+ mHandler = new MyHandler(handler.getLooper());
+ mConstants = new Constants(mHandler);
+
if (systemDir == null) {
mStatsFile = null;
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
} else {
mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, systemDir,
- this::getMaxHistoryFiles);
+ mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES,
+ mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
}
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;
@@ -11247,7 +10668,6 @@ public class BatteryStatsImpl extends BatteryStats {
initTimes(uptimeUs, realtimeUs);
mStartPlatformVersion = mEndPlatformVersion = Build.ID;
initDischarge(realtimeUs);
- clearHistoryLocked();
updateDailyDeadlineLocked();
mPlatformIdleStateCallback = cb;
mMeasuredEnergyRetriever = energyStatsCb;
@@ -11258,12 +10678,6 @@ 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);
@@ -11345,7 +10759,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeUnplugLevel = 0;
mDischargePlugLevel = -1;
mDischargeCurrentLevel = 0;
- mCurrentBatteryLevel = 0;
+ mBatteryLevel = 0;
}
public void setPowerProfileLocked(PowerProfile profile) {
@@ -11732,7 +11146,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
public int getHistoryUsedSize() {
- return mBatteryStatsHistory.getHistoryUsedSize();
+ return mHistory.getHistoryUsedSize();
}
@Override
@@ -11746,43 +11160,27 @@ public class BatteryStatsImpl extends BatteryStats {
*/
@VisibleForTesting
public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
- return new BatteryStatsHistoryIterator(mBatteryStatsHistory);
+ return mHistory.iterate();
}
@Override
public int getHistoryStringPoolSize() {
- return mHistoryTagPool.size();
+ return mHistory.getHistoryStringPoolSize();
}
@Override
public int getHistoryStringPoolBytes() {
- return mNumHistoryTagChars;
+ return mHistory.getHistoryStringPoolBytes();
}
@Override
public String getHistoryTagPoolString(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.string : null;
+ return mHistory.getHistoryTagPoolString(index);
}
@Override
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());
- }
+ return mHistory.getHistoryTagPoolUid(index);
}
@Override
@@ -11792,15 +11190,11 @@ 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;
}
@@ -11853,24 +11247,23 @@ public class BatteryStatsImpl extends BatteryStats {
long realtimeUs = mSecRealtime * 1000;
resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
pullPendingStateUpdatesLocked();
- addHistoryRecordLocked(mSecRealtime, mSecUptime);
- mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
- = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
+ mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
+ mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
- if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
+ if (!mBatteryPluggedIn) {
if (Display.isOnState(mScreenState)) {
- mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
+ mDischargeScreenOnUnplugLevel = mBatteryLevel;
mDischargeScreenDozeUnplugLevel = 0;
mDischargeScreenOffUnplugLevel = 0;
} else if (Display.isDozeState(mScreenState)) {
mDischargeScreenOnUnplugLevel = 0;
- mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
+ mDischargeScreenDozeUnplugLevel = mBatteryLevel;
mDischargeScreenOffUnplugLevel = 0;
} else {
mDischargeScreenOnUnplugLevel = 0;
mDischargeScreenDozeUnplugLevel = 0;
- mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
+ mDischargeScreenOffUnplugLevel = mBatteryLevel;
}
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
@@ -12014,27 +11407,12 @@ 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);
- clearHistoryLocked();
- if (mBatteryStatsHistory != null) {
- mBatteryStatsHistory.resetAllFiles();
- }
+ mHistory.reset();
// Flush external data, gathering snapshots, but don't process it since it is pre-reset data
mIgnoreNextExternalStats = true;
@@ -12057,7 +11435,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++) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
uids.keyAt(j));
}
}
@@ -12482,9 +11860,8 @@ public class BatteryStatsImpl extends BatteryStats {
(long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
monitoredRailChargeConsumedMaMs);
- mHistoryCur.wifiRailChargeMah +=
- (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
+ (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
mTmpRailStats.resetWifiTotalEnergyUsed();
if (uidEstimatedConsumptionMah != null) {
@@ -12597,9 +11974,8 @@ public class BatteryStatsImpl extends BatteryStats {
(long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
monitoredRailChargeConsumedMaMs);
- mHistoryCur.modemRailChargeMah +=
- (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
+ (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
mTmpRailStats.resetCellularTotalEnergyUsed();
}
@@ -12867,8 +12243,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
}
}
@@ -14301,11 +13677,7 @@ public class BatteryStatsImpl extends BatteryStats {
mHandler.removeCallbacks(mDeferSetCharging);
if (mCharging != charging) {
mCharging = charging;
- if (charging) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
- } else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
- }
+ mHistory.setChargingState(charging);
mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
return true;
}
@@ -14319,6 +13691,15 @@ 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) {
@@ -14402,15 +13783,12 @@ 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) {
- mRecordingHistory = true;
- startRecordingHistory(mSecRealtime, mSecUptime, reset);
+ mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
+ initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
}
- addHistoryRecordLocked(mSecRealtime, mSecUptime);
+ mBatteryPluggedIn = false;
+ mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
mDischargeCurrentLevel = mDischargeUnplugLevel = level;
if (Display.isOnState(screenState)) {
mDischargeScreenOnUnplugLevel = level;
@@ -14432,11 +13810,8 @@ public class BatteryStatsImpl extends BatteryStats {
} else {
mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
- 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);
+ mBatteryPluggedIn = true;
+ mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
mDischargeCurrentLevel = mDischargePlugLevel = level;
if (level < mDischargeUnplugLevel) {
mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
@@ -14451,45 +13826,12 @@ public class BatteryStatsImpl extends BatteryStats {
mModStepMode = 0;
}
if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
- if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
+ if (mStatsFile != null && !mHistory.isReadOnly()) {
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);
@@ -14507,8 +13849,7 @@ 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(mHaveBatteryLevel ? mHistoryCur : null,
- status, plugType, level);
+ reportChangesToStatsLog(status, plugType, level);
final boolean onBattery = isOnBattery(plugType, status);
if (!mHaveBatteryLevel) {
@@ -14518,52 +13859,47 @@ 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) {
- if (onBattery) {
- mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- } else {
- mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- }
+ mHistory.setPluggedInState(!onBattery);
}
+ mBatteryStatus = status;
+ mBatteryLevel = level;
+ mBatteryChargeUah = chargeUah;
+
// Always start out assuming charging, that will be updated later.
- mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
- mHistoryCur.batteryStatus = (byte)status;
- mHistoryCur.batteryLevel = (byte)level;
- mHistoryCur.batteryChargeUah = chargeUah;
+ mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
+
mMaxChargeStepLevel = mMinDischargeStepLevel =
mLastChargeStepLevel = mLastDischargeStepLevel = level;
- } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
+ } else if (mBatteryLevel != level || mOnBattery != onBattery) {
recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
}
- int oldStatus = mHistoryCur.batteryStatus;
+ int oldStatus = mBatteryStatus;
if (onBattery) {
mDischargeCurrentLevel = level;
- if (!mRecordingHistory) {
- mRecordingHistory = true;
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
+ if (!mHistory.isRecordingHistory()) {
+ mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
} else if (level < 96 &&
status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
- if (!mRecordingHistory) {
- mRecordingHistory = true;
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
+ if (!mHistory.isRecordingHistory()) {
+ mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
}
- mBatteryVoltageMv = voltageMv;
- mCurrentBatteryLevel = level;
if (mDischargePlugLevel < 0) {
mDischargePlugLevel = level;
}
if (onBattery != mOnBattery) {
- 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) {
+ mBatteryLevel = level;
+ mBatteryStatus = status;
+ mBatteryHealth = health;
+ mBatteryPlugType = plugType;
+ mBatteryTemperature = temp;
+ mBatteryVoltageMv = voltageMv;
+ mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
+ if (chargeUah < mBatteryChargeUah) {
// Only record discharges
- final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
+ final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -14575,12 +13911,12 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
- mHistoryCur.batteryChargeUah = chargeUah;
+ mBatteryChargeUah = chargeUah;
setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
} else {
boolean changed = false;
- if (mHistoryCur.batteryLevel != level) {
- mHistoryCur.batteryLevel = (byte)level;
+ if (mBatteryLevel != level) {
+ mBatteryLevel = level;
changed = true;
// TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
@@ -14588,33 +13924,33 @@ public class BatteryStatsImpl extends BatteryStats {
mExternalSync.scheduleSyncDueToBatteryLevelChange(
mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
}
- if (mHistoryCur.batteryStatus != status) {
- mHistoryCur.batteryStatus = (byte)status;
+ if (mBatteryStatus != status) {
+ mBatteryStatus = status;
changed = true;
}
- if (mHistoryCur.batteryHealth != health) {
- mHistoryCur.batteryHealth = (byte)health;
+ if (mBatteryHealth != health) {
+ mBatteryHealth = health;
changed = true;
}
- if (mHistoryCur.batteryPlugType != plugType) {
- mHistoryCur.batteryPlugType = (byte)plugType;
+ if (mBatteryPlugType != plugType) {
+ mBatteryPlugType = plugType;
changed = true;
}
- if (temp >= (mHistoryCur.batteryTemperature+10)
- || temp <= (mHistoryCur.batteryTemperature-10)) {
- mHistoryCur.batteryTemperature = (short)temp;
+ if (temp >= (mBatteryTemperature + 10)
+ || temp <= (mBatteryTemperature - 10)) {
+ mBatteryTemperature = temp;
changed = true;
}
- if (voltageMv > (mHistoryCur.batteryVoltage + 20)
- || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
- mHistoryCur.batteryVoltage = (char) voltageMv;
+ if (voltageMv > (mBatteryVoltageMv + 20)
+ || voltageMv < (mBatteryVoltageMv - 20)) {
+ mBatteryVoltageMv = voltageMv;
changed = true;
}
- if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
- || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
- if (chargeUah < mHistoryCur.batteryChargeUah) {
+ if (chargeUah >= (mBatteryChargeUah + 10)
+ || chargeUah <= (mBatteryChargeUah - 10)) {
+ if (chargeUah < mBatteryChargeUah) {
// Only record discharges
- final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
+ final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -14626,9 +13962,10 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
- mHistoryCur.batteryChargeUah = chargeUah;
+ mBatteryChargeUah = 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);
@@ -14686,7 +14023,10 @@ public class BatteryStatsImpl extends BatteryStats {
mLastChargeStepLevel = level;
}
if (changed) {
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
+ mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
+ mBatteryChargeUah);
+ mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
}
if (!onBattery &&
@@ -14695,7 +14035,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.
- mRecordingHistory = DEBUG;
+ mHistory.setHistoryRecordingEnabled(DEBUG);
}
mLastLearnedBatteryCapacityUah = chargeFullUah;
@@ -14714,17 +14054,18 @@ public class BatteryStatsImpl extends BatteryStats {
}
// Inform StatsLog of setBatteryState changes.
- // If this is the first reporting, pass in recentPast == null.
- private void reportChangesToStatsLog(HistoryItem recentPast,
- final int status, final int plugType, final int level) {
+ private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
+ if (!mHaveBatteryLevel) {
+ return;
+ }
- if (recentPast == null || recentPast.batteryStatus != status) {
+ if (mBatteryStatus != status) {
FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
}
- if (recentPast == null || recentPast.batteryPlugType != plugType) {
+ if (mBatteryPlugType != plugType) {
FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
}
- if (recentPast == null || recentPast.batteryLevel != level) {
+ if (mBatteryLevel != level) {
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
}
}
@@ -14794,7 +14135,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (msPerLevel <= 0) {
return -1;
}
- return (msPerLevel * mCurrentBatteryLevel) * 1000;
+ return (msPerLevel * mBatteryLevel) * 1000;
}
@Override
@@ -14824,7 +14165,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (msPerLevel <= 0) {
return -1;
}
- return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
+ return (msPerLevel * (100 - mBatteryLevel)) * 1000;
}
/*@hide */
@@ -15255,7 +14596,8 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void shutdownLocked() {
- recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime());
+ mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
+ mClock.currentTimeMillis());
writeSyncLocked();
mShuttingDown = true;
}
@@ -15463,7 +14805,6 @@ 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
@@ -15474,9 +14815,20 @@ 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,
@@ -15697,27 +15049,11 @@ 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;
}
- 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();
- }
+ mHistory.writeHistory();
}
private final ReentrantLock mWriteLock = new ReentrantLock();
@@ -15756,13 +15092,6 @@ 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();
@@ -15775,7 +15104,7 @@ public class BatteryStatsImpl extends BatteryStats {
readSummaryFromParcel(stats);
if (DEBUG) {
Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
- + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
+ + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
- start));
}
}
@@ -15787,126 +15116,19 @@ public class BatteryStatsImpl extends BatteryStats {
stats.recycle();
}
- 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();
+ if (!mHistory.readSummary()) {
+ resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
+ RESET_REASON_CORRUPT_FILE);
}
mEndPlatformVersion = Build.ID;
- 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);
- }
+ mHistory.continueRecordingHistory();
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();
@@ -15916,31 +15138,7 @@ public class BatteryStatsImpl extends BatteryStats {
return;
}
- 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;
- }
+ mHistory.readSummaryFromParcel(in);
mStartCount = in.readInt();
mUptimeUs = in.readLong();
@@ -15953,7 +15151,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeUnplugLevel = in.readInt();
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
- mCurrentBatteryLevel = in.readInt();
+ mBatteryLevel = in.readInt();
mEstimatedBatteryCapacityMah = in.readInt();
mLastLearnedBatteryCapacityUah = in.readInt();
mMinLearnedBatteryCapacityUah = in.readInt();
@@ -16456,19 +15654,7 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(VERSION);
- 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);
- }
+ mHistory.writeSummaryToParcel(out, inclHistory);
out.writeInt(mStartCount);
out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
@@ -16481,7 +15667,7 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(mDischargeUnplugLevel);
out.writeInt(mDischargePlugLevel);
out.writeInt(mDischargeCurrentLevel);
- out.writeInt(mCurrentBatteryLevel);
+ out.writeInt(mBatteryLevel);
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 0cdd4d101459..c36d950b6cf6 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -22,7 +22,6 @@ 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;
@@ -32,10 +31,8 @@ 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;
@@ -220,18 +217,7 @@ public class BatteryUsageStatsProvider {
}
BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;
-
- // 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);
+ batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.copyHistory());
}
BatteryUsageStats stats = batteryUsageStatsBuilder.build();
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
index 06253a08d937..8b30995404f0 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
@@ -220,18 +220,17 @@ public class PowerStatsDataStorage {
public void write(byte[] data) {
if (data != null && data.length > 0) {
mLock.lock();
-
- long currentTimeMillis = System.currentTimeMillis();
try {
+ long currentTimeMillis = System.currentTimeMillis();
DataElement dataElement = new DataElement(data);
mFileRotator.rewriteActive(new DataRewriter(dataElement.toByteArray()),
currentTimeMillis);
mFileRotator.maybeRotate(currentTimeMillis);
} catch (IOException e) {
Slog.e(TAG, "Failed to write to on-device storage: " + e);
+ } finally {
+ mLock.unlock();
}
-
- mLock.unlock();
}
}
@@ -240,21 +239,31 @@ public class PowerStatsDataStorage {
* DataElement retrieved from on-device storage, callback is called.
*/
public void read(DataElementReadCallback callback) throws IOException {
- mFileRotator.readMatching(new DataReader(callback), Long.MIN_VALUE, Long.MAX_VALUE);
+ mLock.lock();
+ try {
+ mFileRotator.readMatching(new DataReader(callback), Long.MIN_VALUE, Long.MAX_VALUE);
+ } finally {
+ mLock.unlock();
+ }
}
/**
* Deletes all stored log data.
*/
public void deleteLogs() {
- File[] files = mDataStorageDir.listFiles();
- for (int i = 0; i < files.length; i++) {
- int versionDot = mDataStorageFilename.lastIndexOf('.');
- String beforeVersionDot = mDataStorageFilename.substring(0, versionDot);
- // Check that the stems before the version match.
- if (files[i].getName().startsWith(beforeVersionDot)) {
- files[i].delete();
+ mLock.lock();
+ try {
+ File[] files = mDataStorageDir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ int versionDot = mDataStorageFilename.lastIndexOf('.');
+ String beforeVersionDot = mDataStorageFilename.substring(0, versionDot);
+ // Check that the stems before the version match.
+ if (files[i].getName().startsWith(beforeVersionDot)) {
+ files[i].delete();
+ }
}
+ } finally {
+ mLock.unlock();
}
}
}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index ca675973b2fd..39ead13b03fe 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -159,12 +159,12 @@ public final class PowerStatsLogger extends Handler {
EnergyMeasurementUtils.packProtoMessage(energyMeasurement, pos);
if (DEBUG) EnergyMeasurementUtils.print(energyMeasurement);
} catch (IOException e) {
- Slog.e(TAG, "Failed to write energy meter data to incident report.");
+ Slog.e(TAG, "Failed to write energy meter data to incident report.", e);
}
}
});
} catch (IOException e) {
- Slog.e(TAG, "Failed to write energy meter info to incident report.");
+ Slog.e(TAG, "Failed to write energy meter info to incident report.", e);
}
pos.flush();
@@ -200,12 +200,12 @@ public final class PowerStatsLogger extends Handler {
EnergyConsumerResultUtils.packProtoMessage(energyConsumerResult, pos, true);
if (DEBUG) EnergyConsumerResultUtils.print(energyConsumerResult);
} catch (IOException e) {
- Slog.e(TAG, "Failed to write energy model data to incident report.");
+ Slog.e(TAG, "Failed to write energy model data to incident report.", e);
}
}
});
} catch (IOException e) {
- Slog.e(TAG, "Failed to write energy model info to incident report.");
+ Slog.e(TAG, "Failed to write energy model info to incident report.", e);
}
pos.flush();
@@ -241,12 +241,12 @@ public final class PowerStatsLogger extends Handler {
StateResidencyResultUtils.packProtoMessage(stateResidencyResult, pos);
if (DEBUG) StateResidencyResultUtils.print(stateResidencyResult);
} catch (IOException e) {
- Slog.e(TAG, "Failed to write residency data to incident report.");
+ Slog.e(TAG, "Failed to write residency data to incident report.", e);
}
}
});
} catch (IOException e) {
- Slog.e(TAG, "Failed to write residency data to incident report.");
+ Slog.e(TAG, "Failed to write residency data to incident report.", e);
}
pos.flush();
@@ -267,7 +267,7 @@ public final class PowerStatsLogger extends Handler {
final FileInputStream fis = new FileInputStream(cachedFile.getPath());
fis.read(dataCached);
} catch (IOException e) {
- Slog.e(TAG, "Failed to read cached data from file");
+ Slog.e(TAG, "Failed to read cached data from file", e);
}
// If the cached and current data are different, delete the data store.
@@ -291,7 +291,7 @@ public final class PowerStatsLogger extends Handler {
fos.write(data);
atomicCachedFile.finishWrite(fos);
} catch (IOException e) {
- Slog.e(TAG, "Failed to write current data to cached file");
+ Slog.e(TAG, "Failed to write current data to cached file", e);
}
}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index cd2b8943ce11..8431f1cc0b4c 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -583,10 +584,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
return;
}
final SpellCheckerInfo sci = spellCheckerMap.get(sciId);
+ final int uid = Binder.getCallingUid();
+ if (!canCallerAccessSpellChecker(sci, uid, userId)) {
+ if (DBG) {
+ Slog.d(TAG, "Spell checker " + sci.getId()
+ + " is not visible to the caller " + uid);
+ }
+ return;
+ }
HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups =
tsd.mSpellCheckerBindGroups;
SpellCheckerBindGroup bindGroup = spellCheckerBindGroups.get(sciId);
- final int uid = Binder.getCallingUid();
if (bindGroup == null) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -649,20 +657,28 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public SpellCheckerInfo[] getEnabledSpellCheckers(@UserIdInt int userId) {
verifyUser(userId);
+ final ArrayList<SpellCheckerInfo> spellCheckerList;
synchronized (mLock) {
final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
if (tsd == null) return null;
- ArrayList<SpellCheckerInfo> spellCheckerList = tsd.mSpellCheckerList;
+ spellCheckerList = new ArrayList<>(tsd.mSpellCheckerList);
+ }
+ int size = spellCheckerList.size();
+ final int callingUid = Binder.getCallingUid();
+ for (int i = size - 1; i >= 0; i--) {
+ if (canCallerAccessSpellChecker(spellCheckerList.get(i), callingUid, userId)) {
+ continue;
+ }
if (DBG) {
- Slog.d(TAG, "getEnabledSpellCheckers: " + spellCheckerList.size());
- for (int i = 0; i < spellCheckerList.size(); ++i) {
- Slog.d(TAG,
- "EnabledSpellCheckers: " + spellCheckerList.get(i).getPackageName());
- }
+ Slog.d(TAG, "Spell checker " + spellCheckerList.get(i).getPackageName()
+ + " is not visible to the caller " + callingUid);
}
- return spellCheckerList.toArray(new SpellCheckerInfo[spellCheckerList.size()]);
+ spellCheckerList.remove(i);
}
+
+ return spellCheckerList.isEmpty() ? null
+ : spellCheckerList.toArray(new SpellCheckerInfo[spellCheckerList.size()]);
}
@Override
@@ -701,6 +717,26 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
}
+ /**
+ * Filter the access to spell checkers by rules of the package visibility. Return {@code true}
+ * if the given spell checker is the currently selected one or visible to the caller.
+ *
+ * @param sci The spell checker to check.
+ * @param callingUid The caller that is going to access the spell checker.
+ * @param userId The user id where the spell checker resides.
+ * @return {@code true} if caller is able to access the spell checker.
+ */
+ private boolean canCallerAccessSpellChecker(@NonNull SpellCheckerInfo sci, int callingUid,
+ @UserIdInt int userId) {
+ final SpellCheckerInfo currentSci = getCurrentSpellCheckerForUser(userId);
+ if (currentSci != null && currentSci.getId().equals(sci.getId())) {
+ return true;
+ }
+ final PackageManagerInternal pmInternal =
+ LocalServices.getService(PackageManagerInternal.class);
+ return !pmInternal.filterAppAccess(sci.getPackageName(), callingUid, userId);
+ }
+
private void setCurrentSpellCheckerLocked(@Nullable SpellCheckerInfo sci, TextServicesData tsd) {
final String sciId = (sci != null) ? sci.getId() : "";
if (DBG) {
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 6162d716b85e..edd1ef36deda 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -39,6 +39,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
@@ -141,6 +142,15 @@ public class TunerResourceManagerService extends SystemService implements IBinde
(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
mPriorityCongfig.parse();
+ // Call SystemProperties.set() in mock app will throw exception because of permission.
+ if (!isForTesting) {
+ final boolean lazyHal = SystemProperties.getBoolean("ro.tuner.lazyhal", false);
+ if (!lazyHal) {
+ // The HAL is not a lazy HAL, enable the tuner server.
+ SystemProperties.set("tuner.server.enable", "true");
+ }
+ }
+
if (mMediaResourceManager == null) {
IBinder mediaResourceManagerBinder = getBinderService("media.resource_manager");
if (mediaResourceManagerBinder == null) {
diff --git a/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java b/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java
index eebd046b2601..be9053055fe3 100644
--- a/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java
@@ -31,9 +31,9 @@ abstract class AbstractVibratorStep extends Step {
public final VibratorController controller;
public final VibrationEffect.Composed effect;
public final int segmentIndex;
- public final long previousStepVibratorOffTimeout;
long mVibratorOnResult;
+ long mPendingVibratorOffDeadline;
boolean mVibratorCompleteCallbackReceived;
/**
@@ -43,19 +43,19 @@ abstract class AbstractVibratorStep extends Step {
* @param controller The vibrator that is playing the effect.
* @param effect The effect being played in this step.
* @param index The index of the next segment to be played by this step
- * @param previousStepVibratorOffTimeout The time the vibrator is expected to complete any
+ * @param pendingVibratorOffDeadline The time the vibrator is expected to complete any
* previous vibration and turn off. This is used to allow this step to
* be triggered when the completion callback is received, and can
* be used to play effects back-to-back.
*/
AbstractVibratorStep(VibrationStepConductor conductor, long startTime,
VibratorController controller, VibrationEffect.Composed effect, int index,
- long previousStepVibratorOffTimeout) {
+ long pendingVibratorOffDeadline) {
super(conductor, startTime);
this.controller = controller;
this.effect = effect;
this.segmentIndex = index;
- this.previousStepVibratorOffTimeout = previousStepVibratorOffTimeout;
+ mPendingVibratorOffDeadline = pendingVibratorOffDeadline;
}
public int getVibratorId() {
@@ -69,27 +69,57 @@ abstract class AbstractVibratorStep extends Step {
@Override
public boolean acceptVibratorCompleteCallback(int vibratorId) {
- boolean isSameVibrator = controller.getVibratorInfo().getId() == vibratorId;
- mVibratorCompleteCallbackReceived |= isSameVibrator;
+ if (getVibratorId() != vibratorId) {
+ return false;
+ }
+
// Only activate this step if a timeout was set to wait for the vibration to complete,
// otherwise we are waiting for the correct time to play the next step.
- return isSameVibrator && (previousStepVibratorOffTimeout > SystemClock.uptimeMillis());
+ boolean shouldAcceptCallback = mPendingVibratorOffDeadline > SystemClock.uptimeMillis();
+ if (VibrationThread.DEBUG) {
+ Slog.d(VibrationThread.TAG,
+ "Received completion callback from " + vibratorId
+ + ", accepted = " + shouldAcceptCallback);
+ }
+
+ // The callback indicates this vibrator has stopped, reset the timeout.
+ mPendingVibratorOffDeadline = 0;
+ mVibratorCompleteCallbackReceived = true;
+ return shouldAcceptCallback;
}
@Override
public List<Step> cancel() {
return Arrays.asList(new CompleteEffectVibratorStep(conductor, SystemClock.uptimeMillis(),
- /* cancelled= */ true, controller, previousStepVibratorOffTimeout));
+ /* cancelled= */ true, controller, mPendingVibratorOffDeadline));
}
@Override
public void cancelImmediately() {
- if (previousStepVibratorOffTimeout > SystemClock.uptimeMillis()) {
+ if (mPendingVibratorOffDeadline > SystemClock.uptimeMillis()) {
// Vibrator might be running from previous steps, so turn it off while canceling.
stopVibrating();
}
}
+ protected long handleVibratorOnResult(long vibratorOnResult) {
+ mVibratorOnResult = vibratorOnResult;
+ if (VibrationThread.DEBUG) {
+ Slog.d(VibrationThread.TAG,
+ "Turned on vibrator " + getVibratorId() + ", result = " + mVibratorOnResult);
+ }
+ if (mVibratorOnResult > 0) {
+ // Vibrator was turned on by this step, with vibratorOnResult as the duration.
+ // Set an extra timeout to wait for the vibrator completion callback.
+ mPendingVibratorOffDeadline = SystemClock.uptimeMillis() + mVibratorOnResult
+ + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT;
+ } else {
+ // Vibrator does not support the request or failed to turn on, reset callback deadline.
+ mPendingVibratorOffDeadline = 0;
+ }
+ return mVibratorOnResult;
+ }
+
protected void stopVibrating() {
if (VibrationThread.DEBUG) {
Slog.d(VibrationThread.TAG,
@@ -97,6 +127,7 @@ abstract class AbstractVibratorStep extends Step {
}
controller.off();
getVibration().stats().reportVibratorOff();
+ mPendingVibratorOffDeadline = 0;
}
protected void changeAmplitude(float amplitude) {
@@ -109,40 +140,29 @@ abstract class AbstractVibratorStep extends Step {
}
/**
- * Return the {@link VibrationStepConductor#nextVibrateStep} with same timings, only jumping
- * the segments.
- */
- protected List<Step> skipToNextSteps(int segmentsSkipped) {
- return nextSteps(startTime, previousStepVibratorOffTimeout, segmentsSkipped);
- }
-
- /**
- * Return the {@link VibrationStepConductor#nextVibrateStep} with same start and off timings
- * calculated from {@link #getVibratorOnDuration()}, jumping all played segments.
- *
- * <p>This method has same behavior as {@link #skipToNextSteps(int)} when the vibrator
- * result is non-positive, meaning the vibrator has either ignored or failed to turn on.
+ * Return the {@link VibrationStepConductor#nextVibrateStep} with start and off timings
+ * calculated from {@link #getVibratorOnDuration()} based on the current
+ * {@link SystemClock#uptimeMillis()} and jumping all played segments from the effect.
*/
protected List<Step> nextSteps(int segmentsPlayed) {
- if (mVibratorOnResult <= 0) {
- // Vibration was not started, so just skip the played segments and keep timings.
- return skipToNextSteps(segmentsPlayed);
+ // Schedule next steps to run right away.
+ long nextStartTime = SystemClock.uptimeMillis();
+ if (mVibratorOnResult > 0) {
+ // Vibrator was turned on by this step, with mVibratorOnResult as the duration.
+ // Schedule next steps for right after the vibration finishes.
+ nextStartTime += mVibratorOnResult;
}
- long nextStartTime = SystemClock.uptimeMillis() + mVibratorOnResult;
- long nextVibratorOffTimeout =
- nextStartTime + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT;
- return nextSteps(nextStartTime, nextVibratorOffTimeout, segmentsPlayed);
+ return nextSteps(nextStartTime, segmentsPlayed);
}
/**
- * Return the {@link VibrationStepConductor#nextVibrateStep} with given start and off timings,
- * which might be calculated independently, jumping all played segments.
+ * Return the {@link VibrationStepConductor#nextVibrateStep} with given start time,
+ * which might be calculated independently, and jumping all played segments from the effect.
*
- * <p>This should be used when the vibrator on/off state is not responsible for the steps
- * execution timings, e.g. while playing the vibrator amplitudes.
+ * <p>This should be used when the vibrator on/off state is not responsible for the step
+ * execution timing, e.g. while playing the vibrator amplitudes.
*/
- protected List<Step> nextSteps(long nextStartTime, long vibratorOffTimeout,
- int segmentsPlayed) {
+ protected List<Step> nextSteps(long nextStartTime, int segmentsPlayed) {
int nextSegmentIndex = segmentIndex + segmentsPlayed;
int effectSize = effect.getSegments().size();
int repeatIndex = effect.getRepeatIndex();
@@ -154,7 +174,7 @@ abstract class AbstractVibratorStep extends Step {
nextSegmentIndex = repeatIndex + ((nextSegmentIndex - effectSize) % loopSize);
}
Step nextStep = conductor.nextVibrateStep(nextStartTime, controller, effect,
- nextSegmentIndex, vibratorOffTimeout);
+ nextSegmentIndex, mPendingVibratorOffDeadline);
return nextStep == null ? VibrationStepConductor.EMPTY_STEP_LIST : Arrays.asList(nextStep);
}
}
diff --git a/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java b/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java
index 8585e3473ef3..fb5140d862b7 100644
--- a/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java
@@ -34,9 +34,9 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep {
private final boolean mCancelled;
CompleteEffectVibratorStep(VibrationStepConductor conductor, long startTime, boolean cancelled,
- VibratorController controller, long previousStepVibratorOffTimeout) {
+ VibratorController controller, long pendingVibratorOffDeadline) {
super(conductor, startTime, controller, /* effect= */ null, /* index= */ -1,
- previousStepVibratorOffTimeout);
+ pendingVibratorOffDeadline);
mCancelled = cancelled;
}
@@ -73,10 +73,11 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep {
return VibrationStepConductor.EMPTY_STEP_LIST;
}
+ long now = SystemClock.uptimeMillis();
float currentAmplitude = controller.getCurrentAmplitude();
long remainingOnDuration =
- previousStepVibratorOffTimeout - VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT
- - SystemClock.uptimeMillis();
+ mPendingVibratorOffDeadline - now
+ - VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT;
long rampDownDuration =
Math.min(remainingOnDuration,
conductor.vibrationSettings.getRampDownDuration());
@@ -89,8 +90,10 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep {
stopVibrating();
return VibrationStepConductor.EMPTY_STEP_LIST;
} else {
+ // Vibration is completing normally, turn off after the deadline in case we
+ // don't receive the callback in time (callback also triggers it right away).
return Arrays.asList(new TurnOffVibratorStep(
- conductor, previousStepVibratorOffTimeout, controller));
+ conductor, mPendingVibratorOffDeadline, controller));
}
}
@@ -100,13 +103,18 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep {
+ " from amplitude " + currentAmplitude
+ " for " + rampDownDuration + "ms");
}
+
+ // If we are cancelling this vibration then make sure the vibrator will be turned off
+ // immediately after the ramp off duration. Otherwise, this is a planned ramp off for
+ // the remaining ON duration, then just propagate the mPendingVibratorOffDeadline so the
+ // turn off step will wait for the vibration completion callback and end gracefully.
+ long rampOffVibratorOffDeadline =
+ mCancelled ? (now + rampDownDuration) : mPendingVibratorOffDeadline;
float amplitudeDelta = currentAmplitude / (rampDownDuration / stepDownDuration);
float amplitudeTarget = currentAmplitude - amplitudeDelta;
- long newVibratorOffTimeout =
- mCancelled ? rampDownDuration : previousStepVibratorOffTimeout;
return Arrays.asList(
new RampOffVibratorStep(conductor, startTime, amplitudeTarget, amplitudeDelta,
- controller, newVibratorOffTimeout));
+ controller, rampOffVibratorOffDeadline));
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
diff --git a/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java b/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java
index f8b99265246a..545ec5bcff03 100644
--- a/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java
@@ -40,11 +40,11 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep {
ComposePrimitivesVibratorStep(VibrationStepConductor conductor, long startTime,
VibratorController controller, VibrationEffect.Composed effect, int index,
- long previousStepVibratorOffTimeout) {
+ long pendingVibratorOffDeadline) {
// This step should wait for the last vibration to finish (with the timeout) and for the
// intended step start time (to respect the effect delays).
- super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect,
- index, previousStepVibratorOffTimeout);
+ super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect,
+ index, pendingVibratorOffDeadline);
}
@Override
@@ -60,18 +60,22 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep {
if (primitives.isEmpty()) {
Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePrimitivesStep: "
+ effect.getSegments().get(segmentIndex));
- return skipToNextSteps(/* segmentsSkipped= */ 1);
+ // Skip this step and play the next one right away.
+ return nextSteps(/* segmentsPlayed= */ 1);
}
if (VibrationThread.DEBUG) {
Slog.d(VibrationThread.TAG, "Compose " + primitives + " primitives on vibrator "
- + controller.getVibratorInfo().getId());
+ + getVibratorId());
}
+
PrimitiveSegment[] primitivesArray =
primitives.toArray(new PrimitiveSegment[primitives.size()]);
- mVibratorOnResult = controller.on(primitivesArray, getVibration().id);
- getVibration().stats().reportComposePrimitives(mVibratorOnResult, primitivesArray);
+ long vibratorOnResult = controller.on(primitivesArray, getVibration().id);
+ handleVibratorOnResult(vibratorOnResult);
+ getVibration().stats().reportComposePrimitives(vibratorOnResult, primitivesArray);
+ // The next start and off times will be calculated from mVibratorOnResult.
return nextSteps(/* segmentsPlayed= */ primitives.size());
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
diff --git a/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java b/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
index 81f52c912f28..8bfa2c3cd082 100644
--- a/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
@@ -41,11 +41,11 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep {
ComposePwleVibratorStep(VibrationStepConductor conductor, long startTime,
VibratorController controller, VibrationEffect.Composed effect, int index,
- long previousStepVibratorOffTimeout) {
+ long pendingVibratorOffDeadline) {
// This step should wait for the last vibration to finish (with the timeout) and for the
// intended step start time (to respect the effect delays).
- super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect,
- index, previousStepVibratorOffTimeout);
+ super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect,
+ index, pendingVibratorOffDeadline);
}
@Override
@@ -61,7 +61,8 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep {
if (pwles.isEmpty()) {
Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePwleStep: "
+ effect.getSegments().get(segmentIndex));
- return skipToNextSteps(/* segmentsSkipped= */ 1);
+ // Skip this step and play the next one right away.
+ return nextSteps(/* segmentsPlayed= */ 1);
}
if (VibrationThread.DEBUG) {
@@ -69,9 +70,11 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep {
+ controller.getVibratorInfo().getId());
}
RampSegment[] pwlesArray = pwles.toArray(new RampSegment[pwles.size()]);
- mVibratorOnResult = controller.on(pwlesArray, getVibration().id);
- getVibration().stats().reportComposePwle(mVibratorOnResult, pwlesArray);
+ long vibratorOnResult = controller.on(pwlesArray, getVibration().id);
+ handleVibratorOnResult(vibratorOnResult);
+ getVibration().stats().reportComposePwle(vibratorOnResult, pwlesArray);
+ // The next start and off times will be calculated from mVibratorOnResult.
return nextSteps(/* segmentsPlayed= */ pwles.size());
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
diff --git a/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java b/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java
index 41902147838d..d91bafa7c8c2 100644
--- a/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java
@@ -35,11 +35,11 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep {
PerformPrebakedVibratorStep(VibrationStepConductor conductor, long startTime,
VibratorController controller, VibrationEffect.Composed effect, int index,
- long previousStepVibratorOffTimeout) {
+ long pendingVibratorOffDeadline) {
// This step should wait for the last vibration to finish (with the timeout) and for the
// intended step start time (to respect the effect delays).
- super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect,
- index, previousStepVibratorOffTimeout);
+ super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect,
+ index, pendingVibratorOffDeadline);
}
@Override
@@ -50,7 +50,8 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep {
if (!(segment instanceof PrebakedSegment)) {
Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a "
+ "PerformPrebakedVibratorStep: " + segment);
- return skipToNextSteps(/* segmentsSkipped= */ 1);
+ // Skip this step and play the next one right away.
+ return nextSteps(/* segmentsPlayed= */ 1);
}
PrebakedSegment prebaked = (PrebakedSegment) segment;
@@ -61,10 +62,11 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep {
}
VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId());
- mVibratorOnResult = controller.on(prebaked, getVibration().id);
- getVibration().stats().reportPerformEffect(mVibratorOnResult, prebaked);
+ long vibratorOnResult = controller.on(prebaked, getVibration().id);
+ handleVibratorOnResult(vibratorOnResult);
+ getVibration().stats().reportPerformEffect(vibratorOnResult, prebaked);
- if (mVibratorOnResult == 0 && prebaked.shouldFallback()
+ if (vibratorOnResult == 0 && prebaked.shouldFallback()
&& (fallback instanceof VibrationEffect.Composed)) {
if (VibrationThread.DEBUG) {
Slog.d(VibrationThread.TAG, "Playing fallback for effect "
@@ -72,14 +74,15 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep {
}
AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller,
replaceCurrentSegment((VibrationEffect.Composed) fallback),
- segmentIndex, previousStepVibratorOffTimeout);
+ segmentIndex, mPendingVibratorOffDeadline);
List<Step> fallbackResult = fallbackStep.play();
// Update the result with the fallback result so this step is seamlessly
// replaced by the fallback to any outer application of this.
- mVibratorOnResult = fallbackStep.getVibratorOnDuration();
+ handleVibratorOnResult(fallbackStep.getVibratorOnDuration());
return fallbackResult;
}
+ // The next start and off times will be calculated from mVibratorOnResult.
return nextSteps(/* segmentsPlayed= */ 1);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
diff --git a/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java b/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java
index 8cf5fb394d9d..84da9f2c58ec 100644
--- a/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java
@@ -30,9 +30,9 @@ final class RampOffVibratorStep extends AbstractVibratorStep {
RampOffVibratorStep(VibrationStepConductor conductor, long startTime, float amplitudeTarget,
float amplitudeDelta, VibratorController controller,
- long previousStepVibratorOffTimeout) {
+ long pendingVibratorOffDeadline) {
super(conductor, startTime, controller, /* effect= */ null, /* index= */ -1,
- previousStepVibratorOffTimeout);
+ pendingVibratorOffDeadline);
mAmplitudeTarget = amplitudeTarget;
mAmplitudeDelta = amplitudeDelta;
}
@@ -68,15 +68,17 @@ final class RampOffVibratorStep extends AbstractVibratorStep {
float newAmplitudeTarget = mAmplitudeTarget - mAmplitudeDelta;
if (newAmplitudeTarget < VibrationStepConductor.RAMP_OFF_AMPLITUDE_MIN) {
- // Vibrator amplitude cannot go further down, just turn it off.
+ // Vibrator amplitude cannot go further down, just turn it off with the configured
+ // deadline that has been adjusted for the scenario when this was triggered by a
+ // cancelled vibration.
return Arrays.asList(new TurnOffVibratorStep(
- conductor, previousStepVibratorOffTimeout, controller));
+ conductor, mPendingVibratorOffDeadline, controller));
}
return Arrays.asList(new RampOffVibratorStep(
conductor,
startTime + conductor.vibrationSettings.getRampStepDuration(),
newAmplitudeTarget, mAmplitudeDelta, controller,
- previousStepVibratorOffTimeout));
+ mPendingVibratorOffDeadline));
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
diff --git a/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java b/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java
index 6fb9111793ea..1672470f1f1a 100644
--- a/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java
@@ -39,26 +39,34 @@ final class SetAmplitudeVibratorStep extends AbstractVibratorStep {
*/
private static final int REPEATING_EFFECT_ON_DURATION = 5000; // 5s
- private long mNextOffTime;
-
SetAmplitudeVibratorStep(VibrationStepConductor conductor, long startTime,
VibratorController controller, VibrationEffect.Composed effect, int index,
- long previousStepVibratorOffTimeout) {
+ long pendingVibratorOffDeadline) {
// This step has a fixed startTime coming from the timings of the waveform it's playing.
- super(conductor, startTime, controller, effect, index, previousStepVibratorOffTimeout);
- mNextOffTime = previousStepVibratorOffTimeout;
+ super(conductor, startTime, controller, effect, index, pendingVibratorOffDeadline);
}
@Override
public boolean acceptVibratorCompleteCallback(int vibratorId) {
- if (controller.getVibratorInfo().getId() == vibratorId) {
- mVibratorCompleteCallbackReceived = true;
- mNextOffTime = SystemClock.uptimeMillis();
+ // Ensure the super method is called and will reset the off timeout and boolean flag.
+ // This is true if the vibrator was ON and this callback has the same vibratorId.
+ if (!super.acceptVibratorCompleteCallback(vibratorId)) {
+ return false;
}
+
// Timings are tightly controlled here, so only trigger this step if the vibrator was
// supposed to be ON but has completed prematurely, to turn it back on as soon as
- // possible.
- return mNextOffTime < startTime && controller.getCurrentAmplitude() > 0;
+ // possible. If the vibrator turned off during a zero-amplitude step, just wait for
+ // the correct start time of this step before playing it.
+ boolean shouldAcceptCallback =
+ (SystemClock.uptimeMillis() < startTime) && (controller.getCurrentAmplitude() > 0);
+
+ if (VibrationThread.DEBUG) {
+ Slog.d(VibrationThread.TAG,
+ "Amplitude step received completion callback from " + vibratorId
+ + ", accepted = " + shouldAcceptCallback);
+ }
+ return shouldAcceptCallback;
}
@Override
@@ -78,40 +86,38 @@ final class SetAmplitudeVibratorStep extends AbstractVibratorStep {
if (mVibratorCompleteCallbackReceived && latency < 0) {
// This step was run early because the vibrator turned off prematurely.
// Turn it back on and return this same step to run at the exact right time.
- mNextOffTime = turnVibratorBackOn(/* remainingDuration= */ -latency);
+ turnVibratorBackOn(/* remainingDuration= */ -latency);
return Arrays.asList(new SetAmplitudeVibratorStep(conductor, startTime, controller,
- effect, segmentIndex, mNextOffTime));
+ effect, segmentIndex, mPendingVibratorOffDeadline));
}
VibrationEffectSegment segment = effect.getSegments().get(segmentIndex);
if (!(segment instanceof StepSegment)) {
Slog.w(VibrationThread.TAG,
"Ignoring wrong segment for a SetAmplitudeVibratorStep: " + segment);
- return skipToNextSteps(/* segmentsSkipped= */ 1);
+ // Use original startTime to avoid propagating latencies to the waveform.
+ return nextSteps(startTime, /* segmentsPlayed= */ 1);
}
StepSegment stepSegment = (StepSegment) segment;
if (stepSegment.getDuration() == 0) {
- // Skip waveform entries with zero timing.
- return skipToNextSteps(/* segmentsSkipped= */ 1);
+ // Use original startTime to avoid propagating latencies to the waveform.
+ return nextSteps(startTime, /* segmentsPlayed= */ 1);
}
float amplitude = stepSegment.getAmplitude();
if (amplitude == 0) {
- if (previousStepVibratorOffTimeout > now) {
+ if (mPendingVibratorOffDeadline > now) {
// Amplitude cannot be set to zero, so stop the vibrator.
stopVibrating();
- mNextOffTime = now;
}
} else {
- if (startTime >= mNextOffTime) {
+ if (startTime >= mPendingVibratorOffDeadline) {
// Vibrator is OFF. Turn vibrator back on for the duration of another
// cycle before setting the amplitude.
long onDuration = getVibratorOnDuration(effect, segmentIndex);
if (onDuration > 0) {
- mVibratorOnResult = startVibrating(onDuration);
- mNextOffTime = now + onDuration
- + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT;
+ startVibrating(onDuration);
}
}
changeAmplitude(amplitude);
@@ -119,27 +125,32 @@ final class SetAmplitudeVibratorStep extends AbstractVibratorStep {
// Use original startTime to avoid propagating latencies to the waveform.
long nextStartTime = startTime + segment.getDuration();
- return nextSteps(nextStartTime, mNextOffTime, /* segmentsPlayed= */ 1);
+ return nextSteps(nextStartTime, /* segmentsPlayed= */ 1);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
- private long turnVibratorBackOn(long remainingDuration) {
+ private void turnVibratorBackOn(long remainingDuration) {
long onDuration = getVibratorOnDuration(effect, segmentIndex);
if (onDuration <= 0) {
// Vibrator is supposed to go back off when this step starts, so just leave it off.
- return previousStepVibratorOffTimeout;
+ return;
}
onDuration += remainingDuration;
+
+ if (VibrationThread.DEBUG) {
+ Slog.d(VibrationThread.TAG,
+ "Turning the vibrator back ON using the remaining duration of "
+ + remainingDuration + "ms, for a total of " + onDuration + "ms");
+ }
+
float expectedAmplitude = controller.getCurrentAmplitude();
- mVibratorOnResult = startVibrating(onDuration);
- if (mVibratorOnResult > 0) {
+ long vibratorOnResult = startVibrating(onDuration);
+ if (vibratorOnResult > 0) {
// Set the amplitude back to the value it was supposed to be playing at.
changeAmplitude(expectedAmplitude);
}
- return SystemClock.uptimeMillis() + onDuration
- + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT;
}
private long startVibrating(long duration) {
@@ -149,6 +160,7 @@ final class SetAmplitudeVibratorStep extends AbstractVibratorStep {
+ duration + "ms");
}
long vibratorOnResult = controller.on(duration, getVibration().id);
+ handleVibratorOnResult(vibratorOnResult);
getVibration().stats().reportVibratorOn(vibratorOnResult);
return vibratorOnResult;
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
index 0799b955b6f1..0af171871792 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
@@ -112,8 +112,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
@Nullable
AbstractVibratorStep nextVibrateStep(long startTime, VibratorController controller,
- VibrationEffect.Composed effect, int segmentIndex,
- long previousStepVibratorOffTimeout) {
+ VibrationEffect.Composed effect, int segmentIndex, long pendingVibratorOffDeadline) {
if (Build.IS_DEBUGGABLE) {
expectIsVibrationThread(true);
}
@@ -123,24 +122,24 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
if (segmentIndex < 0) {
// No more segments to play, last step is to complete the vibration on this vibrator.
return new CompleteEffectVibratorStep(this, startTime, /* cancelled= */ false,
- controller, previousStepVibratorOffTimeout);
+ controller, pendingVibratorOffDeadline);
}
VibrationEffectSegment segment = effect.getSegments().get(segmentIndex);
if (segment instanceof PrebakedSegment) {
return new PerformPrebakedVibratorStep(this, startTime, controller, effect,
- segmentIndex, previousStepVibratorOffTimeout);
+ segmentIndex, pendingVibratorOffDeadline);
}
if (segment instanceof PrimitiveSegment) {
return new ComposePrimitivesVibratorStep(this, startTime, controller, effect,
- segmentIndex, previousStepVibratorOffTimeout);
+ segmentIndex, pendingVibratorOffDeadline);
}
if (segment instanceof RampSegment) {
return new ComposePwleVibratorStep(this, startTime, controller, effect, segmentIndex,
- previousStepVibratorOffTimeout);
+ pendingVibratorOffDeadline);
}
return new SetAmplitudeVibratorStep(this, startTime, controller, effect, segmentIndex,
- previousStepVibratorOffTimeout);
+ pendingVibratorOffDeadline);
}
/** Called when this conductor is going to be started running by the VibrationThread. */
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 2f12a820eb81..d1cde602b391 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -387,8 +387,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
* An internal-only version of vibrate that allows the caller access to the {@link Vibration}.
* The Vibration is only returned if it is ongoing after this method returns.
*/
- @Nullable
@VisibleForTesting
+ @Nullable
Vibration vibrateInternal(int uid, String opPkg, @NonNull CombinedVibration effect,
@Nullable VibrationAttributes attrs, String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
@@ -1844,6 +1844,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
attrs, commonOptions.description, deathBinder);
if (vib != null && !commonOptions.background) {
try {
+ // Waits for the client vibration to finish, but the VibrationThread may still
+ // do cleanup after this.
vib.waitForEnd();
} catch (InterruptedException e) {
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 55d6b2fe8226..c940a658015d 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -375,9 +375,6 @@ public class AppTransition implements Dump {
final AnimationAdapter topOpeningAnim = wc != null ? wc.getAnimation() : null;
int redoLayout = notifyAppTransitionStartingLocked(
- AppTransition.isKeyguardGoingAwayTransitOld(transit),
- AppTransition.isKeyguardOccludeTransitOld(transit),
- topOpeningAnim != null ? topOpeningAnim.getDurationHint() : 0,
topOpeningAnim != null
? topOpeningAnim.getStatusBarTransitionsStartTime()
: SystemClock.uptimeMillis(),
@@ -416,7 +413,7 @@ public class AppTransition implements Dump {
}
void freeze() {
- final boolean keyguardGoingAway = mNextAppTransitionRequests.contains(
+ final boolean keyguardGoingAwayCancelled = mNextAppTransitionRequests.contains(
TRANSIT_KEYGUARD_GOING_AWAY);
// The RemoteAnimationControl didn't register AppTransitionListener and
@@ -429,7 +426,7 @@ public class AppTransition implements Dump {
mNextAppTransitionRequests.clear();
clear();
setReady();
- notifyAppTransitionCancelledLocked(keyguardGoingAway);
+ notifyAppTransitionCancelledLocked(keyguardGoingAwayCancelled);
}
private void setAppTransitionState(int state) {
@@ -479,9 +476,9 @@ public class AppTransition implements Dump {
}
}
- private void notifyAppTransitionCancelledLocked(boolean keyguardGoingAway) {
+ private void notifyAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onAppTransitionCancelledLocked(keyguardGoingAway);
+ mListeners.get(i).onAppTransitionCancelledLocked(keyguardGoingAwayCancelled);
}
}
@@ -491,14 +488,12 @@ public class AppTransition implements Dump {
}
}
- private int notifyAppTransitionStartingLocked(boolean keyguardGoingAway,
- boolean keyguardOcclude, long duration, long statusBarAnimationStartTime,
+ private int notifyAppTransitionStartingLocked(long statusBarAnimationStartTime,
long statusBarAnimationDuration) {
int redoLayout = 0;
for (int i = 0; i < mListeners.size(); i++) {
- redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(keyguardGoingAway,
- keyguardOcclude, duration, statusBarAnimationStartTime,
- statusBarAnimationDuration);
+ redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(
+ statusBarAnimationStartTime, statusBarAnimationDuration);
}
return redoLayout;
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 44f388b6ed39..4b0005d77e40 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -20,10 +20,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
@@ -95,7 +91,6 @@ import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionFlags;
import android.view.WindowManager.TransitionOldType;
import android.view.WindowManager.TransitionType;
-import android.view.animation.Animation;
import android.window.ITaskFragmentOrganizer;
import com.android.internal.annotations.VisibleForTesting;
@@ -297,7 +292,6 @@ public class AppTransitionController {
final int flags = appTransition.getTransitFlags();
layoutRedo = appTransition.goodToGo(transit, topOpeningApp);
- handleNonAppWindowsInTransition(transit, flags);
appTransition.postAnimationCallback();
appTransition.clear();
} finally {
@@ -1171,30 +1165,6 @@ public class AppTransitionController {
}
}
- private void handleNonAppWindowsInTransition(@TransitionOldType int transit, int flags) {
- if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
- && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
- if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
- && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
- && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
- Animation anim = mService.mPolicy.createKeyguardWallpaperExit(
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
- if (anim != null) {
- anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
- mDisplayContent.mWallpaperController.startWallpaperAnimation(anim);
- }
- }
- }
- if ((transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
- || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER)
- && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
- mDisplayContent.startKeyguardExitOnNonAppWindows(
- transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0,
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0);
- }
- }
-
private boolean transitionGoodToGo(ArraySet<? extends WindowContainer> apps,
ArrayMap<WindowContainer, Integer> outReasons) {
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 77737028fd37..1c90bbae79ec 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6586,7 +6586,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
@Override
- public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
+ public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
// It is only needed when freezing display in legacy transition.
if (mTransitionController.isShellTransitionsEnabled()) return;
continueUpdateOrientationForDiffOrienLaunchingApp();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 8e06a810ead1..508e6dc77a61 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -619,9 +619,8 @@ public class DisplayPolicy {
}
@Override
- public int onAppTransitionStartingLocked(boolean keyguardGoingAway,
- boolean keyguardOccluding, long duration,
- long statusBarAnimationStartTime, long statusBarAnimationDuration) {
+ public int onAppTransitionStartingLocked(long statusBarAnimationStartTime,
+ long statusBarAnimationDuration) {
mHandler.post(() -> {
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
@@ -633,7 +632,7 @@ public class DisplayPolicy {
}
@Override
- public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
+ public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
mHandler.post(mAppTransitionCancelled);
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 5b702eac7059..7bb57d827a43 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -161,15 +161,14 @@ public class RecentsAnimationController implements DeathRecipient {
*/
final AppTransitionListener mAppTransitionListener = new AppTransitionListener() {
@Override
- public int onAppTransitionStartingLocked(boolean keyguardGoingAway,
- boolean keyguardOccluding, long duration, long statusBarAnimationStartTime,
+ public int onAppTransitionStartingLocked(long statusBarAnimationStartTime,
long statusBarAnimationDuration) {
continueDeferredCancel();
return 0;
}
@Override
- public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
+ public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
continueDeferredCancel();
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 80b7514d3502..c586b155a222 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -32,13 +32,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -74,7 +68,6 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -82,7 +75,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.SurfaceControl;
import android.view.WindowManager;
-import android.view.animation.Animation;
import android.window.RemoteTransition;
import android.window.TransitionInfo;
@@ -1150,36 +1142,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
private void handleNonAppWindowsInTransition(@NonNull DisplayContent dc,
@TransitionType int transit, @TransitionFlags int flags) {
- if ((transit == TRANSIT_KEYGUARD_GOING_AWAY
- || (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0)
- && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
- if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
- && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
- && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
- Animation anim = mController.mAtm.mWindowManager.mPolicy
- .createKeyguardWallpaperExit(
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
- if (anim != null) {
- anim.scaleCurrentDuration(
- mController.mAtm.mWindowManager.getTransitionAnimationScaleLocked());
- dc.mWallpaperController.startWallpaperAnimation(anim);
- }
- }
- dc.startKeyguardExitOnNonAppWindows(
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0,
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0,
- (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0);
- if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
- // When remote animation is enabled for KEYGUARD_GOING_AWAY transition, SysUI
- // receives IRemoteAnimationRunner#onAnimationStart to start animation, so we don't
- // need to call IKeyguardService#keyguardGoingAway here.
- mController.mAtm.mWindowManager.mPolicy.startKeyguardExitAnimation(
- SystemClock.uptimeMillis(), 0 /* duration */);
- }
- }
if ((flags & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) {
mController.mAtm.mWindowManager.mPolicy.applyKeyguardOcclusionChange(
- true /* keyguardOccludingStarted */);
+ false /* notify */);
}
}
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index f62efbfbd08d..e2438097bce4 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -655,11 +655,9 @@ class TransitionController {
}
void dispatchLegacyAppTransitionStarting(TransitionInfo info, long statusBarTransitionDelay) {
- final boolean keyguardGoingAway = info.isKeyguardGoingAway();
for (int i = 0; i < mLegacyListeners.size(); ++i) {
// TODO(shell-transitions): handle (un)occlude transition.
- mLegacyListeners.get(i).onAppTransitionStartingLocked(keyguardGoingAway,
- false /* keyguardOcclude */, 0 /* durationHint */,
+ mLegacyListeners.get(i).onAppTransitionStartingLocked(
SystemClock.uptimeMillis() + statusBarTransitionDelay,
AnimationAdapter.STATUS_BAR_TRANSITION_DURATION);
}
@@ -674,7 +672,7 @@ class TransitionController {
void dispatchLegacyAppTransitionCancelled() {
for (int i = 0; i < mLegacyListeners.size(); ++i) {
mLegacyListeners.get(i).onAppTransitionCancelledLocked(
- false /* keyguardGoingAway */);
+ false /* keyguardGoingAwayCancelled */);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index a71c3866ba38..11475ac6150b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -220,9 +220,10 @@ public abstract class WindowManagerInternal {
/**
* Called when a pending app transition gets cancelled.
*
- * @param keyguardGoingAway true if keyguard going away transition got cancelled.
+ * @param keyguardGoingAwayCancelled {@code true} if keyguard going away transition was
+ * cancelled.
*/
- public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {}
+ public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {}
/**
* Called when an app transition is timed out.
@@ -232,9 +233,6 @@ public abstract class WindowManagerInternal {
/**
* Called when an app transition gets started
*
- * @param keyguardGoingAway true if keyguard going away transition is started.
- * @param keyguardOccluding true if keyguard (un)occlude transition is started.
- * @param duration the total duration of the transition
* @param statusBarAnimationStartTime the desired start time for all visual animations in
* the status bar caused by this app transition in uptime millis
* @param statusBarAnimationDuration the duration for all visual animations in the status
@@ -245,8 +243,7 @@ public abstract class WindowManagerInternal {
* {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER},
* or {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
*/
- public int onAppTransitionStartingLocked(boolean keyguardGoingAway,
- boolean keyguardOccluding, long duration, long statusBarAnimationStartTime,
+ public int onAppTransitionStartingLocked(long statusBarAnimationStartTime,
long statusBarAnimationDuration) {
return 0;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b4386f6ad206..8025cb296b32 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -425,32 +425,6 @@ public class WindowManagerService extends IWindowManager.Stub
SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, false);
/**
- * Run Keyguard animation as remote animation in System UI instead of local animation in
- * the server process.
- *
- * 0: Runs all keyguard animation as local animation
- * 1: Only runs keyguard going away animation as remote animation
- * 2: Runs all keyguard animation as remote animation
- */
- private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
- "persist.wm.enable_remote_keyguard_animation";
-
- private static final int sEnableRemoteKeyguardAnimation =
- SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 2);
-
- /**
- * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
- */
- public static final boolean sEnableRemoteKeyguardGoingAwayAnimation =
- sEnableRemoteKeyguardAnimation >= 1;
-
- /**
- * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
- */
- public static final boolean sEnableRemoteKeyguardOccludeAnimation =
- sEnableRemoteKeyguardAnimation >= 2;
-
- /**
* Allows a fullscreen windowing mode activity to launch in its desired orientation directly
* when the display has different orientation.
*/
@@ -1118,7 +1092,7 @@ public class WindowManagerService extends IWindowManager.Stub
= new WindowManagerInternal.AppTransitionListener() {
@Override
- public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
+ public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
}
@Override
diff --git a/services/proguard.flags b/services/proguard.flags
index c9303462fb6a..606f360f2cc5 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -104,6 +104,9 @@
-keep,allowoptimization,allowaccessmodification class com.android.server.input.InputManagerService {
<methods>;
}
+-keep,allowoptimization,allowaccessmodification class com.android.server.input.NativeInputManagerService$NativeImpl {
+ <methods>;
+}
-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbHostManager {
*** usbDeviceRemoved(...);
*** usbDeviceAdded(...);
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
index d90d8b8bfac0..5cf026e64f67 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
@@ -68,7 +68,8 @@ public class ScribeTest {
private MockitoSession mMockingSession;
private Scribe mScribeUnderTest;
private File mTestFileDir;
- private final List<InstalledPackageInfo> mInstalledPackages = new ArrayList<>();
+ private final SparseArrayMap<String, InstalledPackageInfo> mInstalledPackages =
+ new SparseArrayMap<>();
private final List<Analyst.Report> mReports = new ArrayList<>();
@Mock
@@ -455,6 +456,6 @@ public class ScribeTest {
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = UserHandle.getUid(userId, Math.abs(pkgName.hashCode()));
pkgInfo.applicationInfo = applicationInfo;
- mInstalledPackages.add(new InstalledPackageInfo(pkgInfo));
+ mInstalledPackages.add(userId, pkgName, new InstalledPackageInfo(pkgInfo));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java
index 842b23c91e41..4a16874c7acf 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java
@@ -17,13 +17,13 @@
package com.android.server.accessibility;
-import static android.view.accessibility.AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS;
import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST;
import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST;
import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID;
import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS;
import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE;
+import static android.view.accessibility.AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
import static android.view.accessibility.AccessibilityNodeInfo.ROOT_NODE_ID;
import static org.junit.Assert.assertEquals;
@@ -528,7 +528,8 @@ public class AccessibilityInteractionControllerNodeRequestsTest {
// different client that holds different fetch flags for TextView1.
sendNodeRequestToController(nodeId, mMockClientCallback2,
mMockClient2InteractionId,
- FLAG_PREFETCH_SIBLINGS | FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
+ FLAG_PREFETCH_SIBLINGS
+ | FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
| FLAG_PREFETCH_ANCESTORS);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
index 5a6d2d398f7d..b7f564094cde 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
+import android.hardware.input.InputDeviceCountryCode;
import android.hardware.input.InputManager;
import android.os.RemoteException;
import android.testing.TestableLooper;
@@ -84,7 +85,7 @@ class InputManagerMockHelper {
final InputDevice device = new InputDevice(mDevices.size() /*id*/, 1 /*generation*/, 0,
inv.getArgument(0) /*name*/, inv.getArgument(1) /*vendorId*/,
inv.getArgument(2) /*productId*/, inv.getArgument(3) /*descriptor*/, true, 0, 0,
- null, false, false, false, false, false);
+ null, InputDeviceCountryCode.INVALID, false, false, false, false, false);
mDevices.add(device);
try {
mDevicesChangedListener.onInputDevicesChanged(
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 0841bfc1d88c..7ce7ac9a84cf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -17,6 +17,7 @@ package com.android.server.pm;
import static com.android.server.pm.permission.CompatibilityPermissionInfo.COMPAT_PERMS;
+import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertArrayEquals;
@@ -101,7 +102,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
@@ -260,6 +260,38 @@ public class PackageParserTest {
}
/**
+ * Extracts the asset file to $mTmpDir/$dirname/$filename.
+ */
+ private File extractFile(String filename, String dirname) throws Exception {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ File dir = new File(mTmpDir, dirname);
+ dir.mkdir();
+ final File tmpFile = new File(dir, filename);
+ try (InputStream inputStream = context.getAssets().openNonAsset(filename)) {
+ Files.copy(inputStream, tmpFile.toPath(), REPLACE_EXISTING);
+ }
+ return tmpFile;
+ }
+
+ /**
+ * Tests the path of cached ParsedPackage.
+ */
+ @Test
+ public void testCache_SameFileName() throws Exception {
+ // Prepare 2 package files with the same name but different paths
+ TestPackageParser2 parser = new TestPackageParser2(mTmpDir);
+ final File f1 = extractFile(TEST_APP1_APK, "dir1");
+ final File f2 = extractFile(TEST_APP1_APK, "dir2");
+ // Sleep for a while so that the cache file will be newer and valid
+ Thread.sleep(1000);
+ ParsedPackage pr1 = parser.parsePackage(f1, 0, true);
+ ParsedPackage pr2 = parser.parsePackage(f2, 0, true);
+ // Check the path of cached ParsedPackage
+ assertThat(pr1.getPath()).isEqualTo(f1.getAbsolutePath());
+ assertThat(pr2.getPath()).isEqualTo(f2.getAbsolutePath());
+ }
+
+ /**
* Tests AndroidManifest.xml with no android:isolatedSplits attribute.
*/
@Test
@@ -632,8 +664,8 @@ public class PackageParserTest {
}
/**
- * A trivial subclass of package parser that only caches the package name, and throws away
- * all other information.
+ * A subclass of package parser that adds a "cache_" prefix to the package name for the cached
+ * results. This is used by tests to tell if a ParsedPackage is generated from the cache or not.
*/
public static class CachePackageNameParser extends PackageParser2 {
@@ -657,15 +689,10 @@ public class PackageParserTest {
void setCacheDir(@NonNull File cacheDir) {
this.mCacher = new PackageCacher(cacheDir) {
@Override
- public byte[] toCacheEntry(ParsedPackage pkg) {
- return ("cache_" + pkg.getPackageName()).getBytes(StandardCharsets.UTF_8);
- }
-
- @Override
public ParsedPackage fromCacheEntry(byte[] cacheEntry) {
- return ((ParsedPackage) PackageImpl.forTesting(
- new String(cacheEntry, StandardCharsets.UTF_8))
- .hideAsParsed());
+ ParsedPackage parsed = super.fromCacheEntry(cacheEntry);
+ parsed.setPackageName("cache_" + parsed.getPackageName());
+ return parsed;
}
};
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt
index 6ee91b89cadc..2332817911f7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt
@@ -17,9 +17,11 @@
package com.android.server.pm.parsing
import android.content.pm.ApplicationInfo
+import java.io.File
-class TestPackageParser2 : PackageParser2(null /* separateProcesses */, null /* displayMetrics */,
- null /* cacheDir */, object : PackageParser2.Callback() {
+class TestPackageParser2(var cacheDir: File? = null) : PackageParser2(
+ null /* separateProcesses */, null /* displayMetrics */,
+ cacheDir /* cacheDir */, object : PackageParser2.Callback() {
override fun isChangeEnabled(changeId: Long, appInfo: ApplicationInfo): Boolean {
return true
}
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 61a7f3853746..5c9348525861 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,6 +28,7 @@ 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;
@@ -49,13 +50,14 @@ 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, BatteryStatsHistory.HISTORY_DIR);
+ mHistoryDir = new File(mSystemDir, "battery-history");
String[] files = mHistoryDir.list();
if (files != null) {
for (int i = 0; i < files.length; i++) {
@@ -67,8 +69,8 @@ public class BatteryStatsHistoryTest {
@Test
public void testConstruct() {
- BatteryStatsHistory history =
- new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
+ BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ null, mClock);
createActiveFile(history);
verifyFileNumbers(history, Arrays.asList(0));
verifyActiveFile(history, "0.bin");
@@ -76,8 +78,8 @@ public class BatteryStatsHistoryTest {
@Test
public void testStartNextFile() {
- BatteryStatsHistory history =
- new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
+ BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ null, mClock);
List<Integer> fileList = new ArrayList<>();
fileList.add(0);
createActiveFile(history);
@@ -114,13 +116,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);
- // verify construct can pick up all files from file system.
+ BatteryStatsHistory history2 = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ null, mClock);
+ // verify constructor can pick up all files from file system.
verifyFileNumbers(history2, fileList);
verifyActiveFile(history2, "33.bin");
- history2.resetAllFiles();
+ history2.reset();
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 713e78638b95..570b2ee617f5 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,6 +63,7 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
MockBatteryStatsImpl(Clock clock, File historyDirectory) {
super(clock, historyDirectory);
initTimersAndCounters();
+ setMaxHistoryBuffer(128 * 1024);
setExternalStatsSyncLocked(mExternalStatsSync);
informThatAllExternalStatsAreFlushed();
@@ -104,12 +105,6 @@ 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;
}
@@ -201,12 +196,14 @@ 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/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index 3f9caa95df4a..ec4ad8965f7d 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -33,6 +33,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
+import android.hardware.input.InputDeviceCountryCode;
import android.hardware.input.InputManager;
import android.os.CombinedVibration;
import android.os.Handler;
@@ -328,7 +329,8 @@ public class InputDeviceDelegateTest {
private InputDevice createInputDevice(int id, boolean hasVibrator) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
- null, hasVibrator, false, false, false /* hasSensor */, false /* hasBattery */);
+ null, InputDeviceCountryCode.INVALID, hasVibrator, false, false,
+ false /* hasSensor */, false /* hasBattery */);
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index ca162efe0f6e..efc240d3f172 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -574,7 +574,7 @@ public class VibrationThreadTest {
}
@Test
- public void vibrate_singleVibratorComposedAndNoCapability_ignoresVibration() throws Exception {
+ public void vibrate_singleVibratorComposedAndNoCapability_ignoresVibration() {
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
@@ -666,6 +666,47 @@ public class VibrationThreadTest {
}
@Test
+ public void vibrate_singleVibratorComposedWithFallback_replacedInTheMiddleOfComposition() {
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+ fakeVibrator.setSupportedPrimitives(
+ VibrationEffect.Composition.PRIMITIVE_CLICK,
+ VibrationEffect.Composition.PRIMITIVE_TICK);
+ fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+
+ long vibrationId = 1;
+ VibrationEffect fallback = VibrationEffect.createOneShot(10, 100);
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+ .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_TICK))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
+ .compose();
+ Vibration vib = createVibration(vibrationId, CombinedVibration.createParallel(effect));
+ vib.addFallback(VibrationEffect.EFFECT_TICK, fallback);
+ startThreadAndDispatcher(vib);
+ waitForCompletion();
+
+ // Use first duration the vibrator is turned on since we cannot estimate the clicks.
+ verify(mManagerHooks).noteVibratorOn(eq(UID), anyLong());
+ verify(mManagerHooks).noteVibratorOff(eq(UID));
+ verify(mControllerCallbacks, times(4)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
+
+ List<VibrationEffectSegment> segments =
+ mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId);
+ assertTrue("Wrong segments: " + segments, segments.size() >= 4);
+ assertTrue(segments.get(0) instanceof PrebakedSegment);
+ assertTrue(segments.get(1) instanceof PrimitiveSegment);
+ for (int i = 2; i < segments.size() - 1; i++) {
+ // One or more step segments as fallback for the EFFECT_TICK.
+ assertTrue(segments.get(i) instanceof StepSegment);
+ }
+ assertTrue(segments.get(segments.size() - 1) instanceof PrimitiveSegment);
+ }
+
+ @Test
public void vibrate_singleVibratorPwle_runsComposePwle() throws Exception {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 36bec750e3bc..1a8df719c223 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -46,6 +46,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManagerInternal;
import android.hardware.input.IInputManager;
+import android.hardware.input.InputDeviceCountryCode;
import android.hardware.input.InputManager;
import android.hardware.vibrator.IVibrator;
import android.hardware.vibrator.IVibratorManager;
@@ -72,6 +73,7 @@ import android.os.VibratorInfo;
import android.os.test.TestLooper;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
+import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.platform.test.annotations.Presubmit;
@@ -99,6 +101,7 @@ import org.mockito.junit.MockitoRule;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -391,22 +394,22 @@ public class VibratorManagerServiceTest {
IVibratorStateListener listenerMock = mockVibratorStateListener();
service.registerVibratorStateListener(1, listenerMock);
- vibrate(service, VibrationEffect.createOneShot(40, 100), ALARM_ATTRS);
- // Wait until service knows vibrator is on.
- assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
- // Wait until effect ends.
- assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+ long oneShotDuration = 20;
+ vibrateAndWaitUntilFinished(service,
+ VibrationEffect.createOneShot(oneShotDuration, VibrationEffect.DEFAULT_AMPLITUDE),
+ ALARM_ATTRS);
InOrder inOrderVerifier = inOrder(listenerMock);
// First notification done when listener is registered.
inOrderVerifier.verify(listenerMock).onVibrating(eq(false));
inOrderVerifier.verify(listenerMock).onVibrating(eq(true));
- inOrderVerifier.verify(listenerMock).onVibrating(eq(false));
+ // The last notification is after the vibration has completed.
+ inOrderVerifier.verify(listenerMock, timeout(TEST_TIMEOUT_MILLIS)).onVibrating(eq(false));
inOrderVerifier.verifyNoMoreInteractions();
InOrder batteryVerifier = inOrder(mBatteryStatsMock);
batteryVerifier.verify(mBatteryStatsMock)
- .noteVibratorOn(UID, 40 + mVibrationConfig.getRampDownDurationMs());
+ .noteVibratorOn(UID, oneShotDuration + mVibrationConfig.getRampDownDurationMs());
batteryVerifier.verify(mBatteryStatsMock).noteVibratorOff(UID);
}
@@ -577,22 +580,18 @@ public class VibratorManagerServiceTest {
setRingerMode(AudioManager.RINGER_MODE_SILENT);
VibratorManagerService service = createSystemReadyService();
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
- // Wait before checking it never played.
- assertFalse(waitUntil(s -> !fakeVibrator.getAllEffectSegments().isEmpty(),
- service, /* timeout= */ 50));
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ RINGTONE_ATTRS);
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
service = createSystemReadyService();
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK), RINGTONE_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 1,
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(
+ service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK), RINGTONE_ATTRS);
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
service = createSystemReadyService();
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK), RINGTONE_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 2,
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(
+ service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK), RINGTONE_ATTRS);
assertEquals(
Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_HEAVY_CLICK),
@@ -607,27 +606,18 @@ public class VibratorManagerServiceTest {
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_TICK, VibrationEffect.EFFECT_CLICK,
VibrationEffect.EFFECT_HEAVY_CLICK, VibrationEffect.EFFECT_DOUBLE_CLICK);
VibratorManagerService service = createSystemReadyService();
- mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
- // The haptic feedback should be ignored in low power, but not the ringtone. The end
- // of the test asserts which actual effects ended up playing.
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK), HAPTIC_FEEDBACK_ATTRS);
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 1,
- service, TEST_TIMEOUT_MILLIS));
- // Allow the ringtone to complete, as the other vibrations won't cancel it.
- assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+ mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK),
+ HAPTIC_FEEDBACK_ATTRS);
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ RINGTONE_ATTRS);
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK),
- /* attrs= */ null);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 2,
- service, TEST_TIMEOUT_MILLIS));
-
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK),
- NOTIFICATION_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 3,
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service,
+ VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK), /* attrs= */ null);
+ vibrateAndWaitUntilFinished(service,
+ VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK), NOTIFICATION_ATTRS);
assertEquals(
Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK),
@@ -693,22 +683,17 @@ public class VibratorManagerServiceTest {
Vibrator.VIBRATION_INTENSITY_HIGH);
VibratorManagerService service = createSystemReadyService();
- VibrationAttributes enforceFreshAttrs = new VibrationAttributes.Builder()
+ VibrationAttributes notificationWithFreshAttrs = new VibrationAttributes.Builder()
.setUsage(VibrationAttributes.USAGE_NOTIFICATION)
.setFlags(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)
.build();
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
Vibrator.VIBRATION_INTENSITY_LOW);
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), NOTIFICATION_ATTRS);
- // VibrationThread will start this vibration async, so wait before vibrating a second time.
- assertTrue(waitUntil(s -> mVibratorProviders.get(0).getAllEffectSegments().size() > 0,
- service, TEST_TIMEOUT_MILLIS));
-
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK), enforceFreshAttrs);
- // VibrationThread will start this vibration async, so wait before checking.
- assertTrue(waitUntil(s -> mVibratorProviders.get(0).getAllEffectSegments().size() > 1,
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ NOTIFICATION_ATTRS);
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK),
+ notificationWithFreshAttrs);
assertEquals(
Arrays.asList(
@@ -784,21 +769,22 @@ public class VibratorManagerServiceTest {
vibrate(service, repeatingEffect, new VibrationAttributes.Builder().setUsage(
VibrationAttributes.USAGE_UNKNOWN).build());
- // VibrationThread will start this vibration async, so wait before checking it started.
+ // VibrationThread will start this vibration async, wait until it has started.
assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
service, TEST_TIMEOUT_MILLIS));
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), HAPTIC_FEEDBACK_ATTRS);
-
- // Wait before checking it never played a second effect.
- assertFalse(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1,
- service, /* timeout= */ 50));
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ HAPTIC_FEEDBACK_ATTRS);
// The time estimate is recorded when the vibration starts, repeating vibrations
// are capped at BATTERY_STATS_REPEATING_VIBRATION_DURATION (=5000).
verify(mBatteryStatsMock).noteVibratorOn(UID, 5000);
// The second vibration shouldn't have recorded that the vibrators were turned on.
verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong());
+ // No segment played is the prebaked CLICK from the second vibration.
+ assertFalse(
+ mVibratorProviders.get(1).getAllEffectSegments().stream()
+ .anyMatch(segment -> segment instanceof PrebakedSegment));
}
@Test
@@ -811,7 +797,7 @@ public class VibratorManagerServiceTest {
new long[]{10_000, 10_000}, new int[]{128, 255}, -1);
vibrate(service, alarmEffect, ALARM_ATTRS);
- // VibrationThread will start this vibration async, so wait before checking it started.
+ // VibrationThread will start this vibration async, wait until it has started.
assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
service, TEST_TIMEOUT_MILLIS));
@@ -841,14 +827,15 @@ public class VibratorManagerServiceTest {
assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
service, TEST_TIMEOUT_MILLIS));
- vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS);
-
- // Wait before checking it never played a second effect.
- assertFalse(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1,
- service, /* timeout= */ 50));
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ HAPTIC_FEEDBACK_ATTRS);
// The second vibration shouldn't have recorded that the vibrators were turned on.
verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong());
+ // The second vibration shouldn't have played any prebaked segment.
+ assertFalse(
+ mVibratorProviders.get(1).getAllEffectSegments().stream()
+ .anyMatch(segment -> segment instanceof PrebakedSegment));
}
@Test
@@ -856,6 +843,7 @@ public class VibratorManagerServiceTest {
throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+ mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
VibratorManagerService service = createSystemReadyService();
VibrationEffect effect = VibrationEffect.createWaveform(
@@ -866,14 +854,16 @@ public class VibratorManagerServiceTest {
assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
service, TEST_TIMEOUT_MILLIS));
- vibrate(service, effect, RINGTONE_ATTRS);
-
- // VibrationThread will start this vibration async, so wait before checking it started.
- assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1,
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ RINGTONE_ATTRS);
// The second vibration should have recorded that the vibrators were turned on.
verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong());
+ // One segment played is the prebaked CLICK from the second vibration.
+ assertEquals(1,
+ mVibratorProviders.get(1).getAllEffectSegments().stream()
+ .filter(PrebakedSegment.class::isInstance)
+ .count());
}
@Test
@@ -892,12 +882,10 @@ public class VibratorManagerServiceTest {
CombinedVibration effect = CombinedVibration.createParallel(
VibrationEffect.createOneShot(10, 10));
- vibrate(service, effect, ALARM_ATTRS);
- verify(mIInputManagerMock).vibrateCombined(eq(1), eq(effect), any());
+ vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS);
- // VibrationThread will start this vibration async, so wait before checking it never played.
- assertFalse(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
- service, /* timeout= */ 50));
+ verify(mIInputManagerMock).vibrateCombined(eq(1), eq(effect), any());
+ assertTrue(mVibratorProviders.get(1).getAllEffectSegments().isEmpty());
}
@Test
@@ -992,9 +980,7 @@ public class VibratorManagerServiceTest {
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
.compose())
.combine();
- vibrate(service, effect, ALARM_ATTRS);
- assertTrue(waitUntil(s -> !fakeVibrator1.getAllEffectSegments().isEmpty(), service,
- TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS);
verify(mNativeWrapperMock).prepareSynced(eq(new int[]{1, 2}));
verify(mNativeWrapperMock).triggerSynced(anyLong());
@@ -1016,9 +1002,7 @@ public class VibratorManagerServiceTest {
.addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.addVibrator(2, VibrationEffect.createOneShot(10, 100))
.combine();
- vibrate(service, effect, ALARM_ATTRS);
- assertTrue(waitUntil(s -> !fakeVibrator1.getAllEffectSegments().isEmpty(), service,
- TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS);
verify(mNativeWrapperMock, never()).prepareSynced(any());
verify(mNativeWrapperMock, never()).triggerSynced(anyLong());
@@ -1036,9 +1020,7 @@ public class VibratorManagerServiceTest {
.addVibrator(1, VibrationEffect.createOneShot(10, 50))
.addVibrator(2, VibrationEffect.createOneShot(10, 100))
.combine();
- vibrate(service, effect, ALARM_ATTRS);
- assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS);
verify(mNativeWrapperMock).prepareSynced(eq(new int[]{1, 2}));
verify(mNativeWrapperMock, never()).triggerSynced(anyLong());
@@ -1057,9 +1039,7 @@ public class VibratorManagerServiceTest {
.addVibrator(1, VibrationEffect.createOneShot(10, 50))
.addVibrator(2, VibrationEffect.createOneShot(10, 100))
.combine();
- vibrate(service, effect, ALARM_ATTRS);
- assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
- service, TEST_TIMEOUT_MILLIS));
+ vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS);
verify(mNativeWrapperMock).prepareSynced(eq(new int[]{1, 2}));
verify(mNativeWrapperMock).triggerSynced(anyLong());
@@ -1096,28 +1076,21 @@ public class VibratorManagerServiceTest {
VibrationEffect.Composition.PRIMITIVE_TICK);
VibratorManagerService service = createSystemReadyService();
- vibrate(service, VibrationEffect.startComposition()
+ vibrateAndWaitUntilFinished(service, VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
.compose(), HAPTIC_FEEDBACK_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 1,
- service, TEST_TIMEOUT_MILLIS));
- vibrate(service, CombinedVibration.startSequential()
+ vibrateAndWaitUntilFinished(service, CombinedVibration.startSequential()
.addNext(1, VibrationEffect.createOneShot(100, 125))
.combine(), NOTIFICATION_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 2,
- service, TEST_TIMEOUT_MILLIS));
- vibrate(service, VibrationEffect.startComposition()
+ vibrateAndWaitUntilFinished(service, VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
.compose(), ALARM_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 3,
- service, TEST_TIMEOUT_MILLIS));
// Ring vibrations have intensity OFF and are not played.
- vibrate(service, VibrationEffect.createOneShot(100, 125), RINGTONE_ATTRS);
- assertFalse(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() > 3,
- service, /* timeout= */ 50));
+ vibrateAndWaitUntilFinished(service, VibrationEffect.createOneShot(100, 125),
+ RINGTONE_ATTRS);
// Only 3 effects played successfully.
assertEquals(3, fakeVibrator.getAllEffectSegments().size());
@@ -1145,6 +1118,7 @@ public class VibratorManagerServiceTest {
.combine(),
HAPTIC_FEEDBACK_ATTRS);
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
@@ -1159,14 +1133,50 @@ public class VibratorManagerServiceTest {
VibratorManagerService service = createSystemReadyService();
vibrate(service, VibrationEffect.createOneShot(1000, 100), HAPTIC_FEEDBACK_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
service.updateServiceState();
+
// Vibration is not stopped nearly after updating service.
assertFalse(waitUntil(s -> !s.isVibrating(1), service, 50));
}
@Test
+ public void vibrate_prebakedAndComposedVibrationsWithFallbacks_playsFallbackOnlyForPredefined()
+ throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+ mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+ mVibratorProviders.get(1).setSupportedPrimitives(
+ VibrationEffect.Composition.PRIMITIVE_CLICK);
+
+ VibratorManagerService service = createSystemReadyService();
+ vibrateAndWaitUntilFinished(service,
+ VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose(),
+ ALARM_ATTRS);
+
+ List<VibrationEffectSegment> segments = mVibratorProviders.get(1).getAllEffectSegments();
+ // At least one step segment played as fallback for unusupported vibration effect
+ assertTrue(segments.size() > 2);
+ // 0: Supported effect played
+ assertTrue(segments.get(0) instanceof PrebakedSegment);
+ // 1: No segment for unsupported primitive
+ // 2: One or more intermediate step segments as fallback for unsupported effect
+ for (int i = 1; i < segments.size() - 1; i++) {
+ assertTrue(segments.get(i) instanceof StepSegment);
+ }
+ // 3: Supported primitive played
+ assertTrue(segments.get(segments.size() - 1) instanceof PrimitiveSegment);
+ }
+
+ @Test
public void cancelVibrate_withoutUsageFilter_stopsVibrating() throws Exception {
mockVibrators(1);
VibratorManagerService service = createSystemReadyService();
@@ -1175,9 +1185,13 @@ public class VibratorManagerServiceTest {
assertFalse(service.isVibrating(1));
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
+
+ // Alarm cancelled on filter match all.
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
}
@@ -1187,6 +1201,8 @@ public class VibratorManagerServiceTest {
VibratorManagerService service = createSystemReadyService();
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
// Vibration is not cancelled with a different usage.
@@ -1216,6 +1232,8 @@ public class VibratorManagerServiceTest {
VibratorManagerService service = createSystemReadyService();
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), attrs);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
// Do not cancel UNKNOWN vibration when filter is being applied for other usages.
@@ -1232,6 +1250,8 @@ public class VibratorManagerServiceTest {
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), attrs);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
// Cancel UNKNOWN vibration when all vibrations are being cancelled.
@@ -1312,6 +1332,8 @@ public class VibratorManagerServiceTest {
VibrationEffect effect = VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100);
vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
@@ -1793,7 +1815,8 @@ public class VibratorManagerServiceTest {
private InputDevice createInputDeviceWithVibrator(int id) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
- null, /* hasVibrator= */ true, false, false, false, false);
+ null, InputDeviceCountryCode.INVALID, /* hasVibrator= */ true, false, false, false,
+ false);
}
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 8546763aebec..88e58eab58aa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -281,7 +281,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
verify(mMockRunner).onAnimationCanceled(null /* taskIds */, null /* taskSnapshots */);
// Simulate the app transition finishing
- mController.mAppTransitionListener.onAppTransitionStartingLocked(false, false, 0, 0, 0);
+ mController.mAppTransitionListener.onAppTransitionStartingLocked(0, 0);
verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, false);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index d2cb7ba5d311..13da1543cfb8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -310,11 +310,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
}
@Override
- public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
+ public void startKeyguardExitAnimation(long startTime) {
}
@Override
- public int applyKeyguardOcclusionChange(boolean keyguardOccludingStarted) {
+ public int applyKeyguardOcclusionChange(boolean notify) {
return 0;
}
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
index 63500774816a..836d406d903c 100644
--- a/tests/Input/src/com/android/test/input/InputDeviceTest.java
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -17,8 +17,8 @@
package android.view;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import android.hardware.input.InputDeviceCountryCode;
import android.os.Parcel;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -55,11 +55,12 @@ public class InputDeviceTest {
assertEquals(device.isExternal(), outDevice.isExternal());
assertEquals(device.getSources(), outDevice.getSources());
assertEquals(device.getKeyboardType(), outDevice.getKeyboardType());
+ assertEquals(device.getCountryCode(), outDevice.getCountryCode());
assertEquals(device.getMotionRanges().size(), outDevice.getMotionRanges().size());
KeyCharacterMap keyCharacterMap = device.getKeyCharacterMap();
KeyCharacterMap outKeyCharacterMap = outDevice.getKeyCharacterMap();
- assertTrue("keyCharacterMap not equal", keyCharacterMap.equals(outKeyCharacterMap));
+ assertEquals("keyCharacterMap not equal", keyCharacterMap, outKeyCharacterMap);
for (int j = 0; j < device.getMotionRanges().size(); j++) {
assertMotionRangeEquals(device.getMotionRanges().get(j),
@@ -70,10 +71,11 @@ public class InputDeviceTest {
private void assertInputDeviceParcelUnparcel(KeyCharacterMap keyCharacterMap) {
final InputDevice device =
new InputDevice(DEVICE_ID, 0 /* generation */, 0 /* controllerNumber */, "name",
- 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
- 0 /* sources */, 0 /* keyboardType */, keyCharacterMap,
- false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
- true /* hasSensor */, false /* hasBattery */);
+ 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
+ 0 /* sources */, 0 /* keyboardType */, keyCharacterMap,
+ InputDeviceCountryCode.INTERNATIONAL, false /* hasVibrator */,
+ false /* hasMicrophone */, false /* hasButtonUnderpad */,
+ true /* hasSensor */, false /* hasBattery */);
Parcel parcel = Parcel.obtain();
device.writeToParcel(parcel, 0);
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 44265511ee50..f1fc503c8556 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -169,6 +169,12 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
assertTrue(getDevice().pushFile(apex, "/" + partition + "/apex/" + fileName));
}
+ private void installTestApex(String fileName, String... extraArgs) throws Exception {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
+ final File apex = buildHelper.getTestFile(fileName);
+ getDevice().installPackage(apex, false, extraArgs);
+ }
+
private void pushTestVendorApexAllowList(String installerPackageName) throws Exception {
if (!getDevice().isAdbRoot()) {
getDevice().enableAdbRoot();
@@ -551,7 +557,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
pushTestApex(REBOOTLESS_V1, "vendor");
getDevice().reboot();
runPhase("testVendorApex_VerifyFactory");
- installPackage(REBOOTLESS_V2, "--staged");
+ installTestApex(REBOOTLESS_V2, "--staged");
getDevice().reboot();
runPhase("testVendorApex_VerifyData");
}
@@ -565,7 +571,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
pushTestApex(REBOOTLESS_V1, "vendor");
getDevice().reboot();
runPhase("testVendorApex_VerifyFactory");
- installPackage(REBOOTLESS_V2, "--force-non-staged");
+ installTestApex(REBOOTLESS_V2, "--force-non-staged");
runPhase("testVendorApex_VerifyData");
}
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index ebe9b5706bf8..edd6dd3468ef 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -30,6 +30,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Field;
import java.util.Map;
/**
@@ -45,6 +46,9 @@ public class TestableLooper {
* catch crashes.
*/
public static final boolean HOLD_MAIN_THREAD = false;
+ private static final Field MESSAGE_QUEUE_MESSAGES_FIELD;
+ private static final Field MESSAGE_NEXT_FIELD;
+ private static final Field MESSAGE_WHEN_FIELD;
private Looper mLooper;
private MessageQueue mQueue;
@@ -54,6 +58,19 @@ public class TestableLooper {
private Runnable mEmptyMessage;
private TestLooperManager mQueueWrapper;
+ static {
+ try {
+ MESSAGE_QUEUE_MESSAGES_FIELD = MessageQueue.class.getDeclaredField("mMessages");
+ MESSAGE_QUEUE_MESSAGES_FIELD.setAccessible(true);
+ MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
+ MESSAGE_NEXT_FIELD.setAccessible(true);
+ MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
+ MESSAGE_WHEN_FIELD.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Failed to initialize TestableLooper", e);
+ }
+ }
+
public TestableLooper(Looper l) throws Exception {
this(acquireLooperManager(l), l);
}
@@ -119,6 +136,33 @@ public class TestableLooper {
while (processQueuedMessages() != 0) ;
}
+ public void moveTimeForward(long milliSeconds) {
+ try {
+ Message msg = getMessageLinkedList();
+ while (msg != null) {
+ long updatedWhen = msg.getWhen() - milliSeconds;
+ if (updatedWhen < 0) {
+ updatedWhen = 0;
+ }
+ MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
+ msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Access failed in TestableLooper: set - Message.when", e);
+ }
+ }
+
+ private Message getMessageLinkedList() {
+ try {
+ MessageQueue queue = mLooper.getQueue();
+ return (Message) MESSAGE_QUEUE_MESSAGES_FIELD.get(queue);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Access failed in TestableLooper: get - MessageQueue.mMessages",
+ e);
+ }
+ }
+
private int processQueuedMessages() {
int count = 0;
mEmptyMessage = () -> { };
diff --git a/tests/testables/tests/AndroidManifest.xml b/tests/testables/tests/AndroidManifest.xml
index 1731f6be4bf2..2bfb04fdb765 100644
--- a/tests/testables/tests/AndroidManifest.xml
+++ b/tests/testables/tests/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
- <application android:debuggable="true" android:testOnly="true">
+ <application android:debuggable="true">
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/testables/tests/AndroidTest.xml b/tests/testables/tests/AndroidTest.xml
deleted file mode 100644
index de1165fca1a2..000000000000
--- a/tests/testables/tests/AndroidTest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-<configuration description="Runs Testable Tests.">
- <option name="test-tag" value="TestablesTests" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="install-arg" value="-t" />
- <option name="test-file-name" value="TestablesTests.apk" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest">
- <option name="package" value="com.android.testables"/>
- </test>
-</configuration> \ No newline at end of file
diff --git a/tests/testables/tests/src/android/testing/TestableLooperTest.java b/tests/testables/tests/src/android/testing/TestableLooperTest.java
index 25f6a48871d3..0f491b86626c 100644
--- a/tests/testables/tests/src/android/testing/TestableLooperTest.java
+++ b/tests/testables/tests/src/android/testing/TestableLooperTest.java
@@ -19,15 +19,19 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.InOrder;
import android.os.Handler;
import android.os.Looper;
@@ -162,7 +166,7 @@ public class TestableLooperTest {
@Test
public void testCorrectLooperExecution() throws Exception {
- boolean[] hasRun = new boolean[] { false };
+ boolean[] hasRun = new boolean[]{false};
Runnable r = () -> {
assertEquals("Should run on main looper", Looper.getMainLooper(), Looper.myLooper());
hasRun[0] = true;
@@ -177,4 +181,63 @@ public class TestableLooperTest {
testableLooper.destroy();
}
}
+
+ @Test
+ public void testDelayedDispatchNoTimeMove() {
+ Handler handler = spy(new Handler(mTestableLooper.getLooper()));
+ InOrder inOrder = inOrder(handler);
+
+ final Message messageA = handler.obtainMessage(1);
+ final Message messageB = handler.obtainMessage(2);
+
+ handler.sendMessageDelayed(messageA, 0);
+ handler.sendMessageDelayed(messageB, 0);
+
+ mTestableLooper.processAllMessages();
+
+ inOrder.verify(handler).dispatchMessage(messageA);
+ inOrder.verify(handler).dispatchMessage(messageB);
+ }
+
+ @Test
+ public void testDelayedMessageDoesntSend() {
+ Handler handler = spy(new Handler(mTestableLooper.getLooper()));
+ InOrder inOrder = inOrder(handler);
+
+ final Message messageA = handler.obtainMessage(1);
+ final Message messageB = handler.obtainMessage(2);
+ final Message messageC = handler.obtainMessage(3);
+
+ handler.sendMessageDelayed(messageA, 0);
+ handler.sendMessageDelayed(messageB, 0);
+ handler.sendMessageDelayed(messageC, 500);
+
+ mTestableLooper.processAllMessages();
+
+ inOrder.verify(handler).dispatchMessage(messageA);
+ inOrder.verify(handler).dispatchMessage(messageB);
+ verify(handler, never()).dispatchMessage(messageC);
+ }
+
+ @Test
+ public void testMessageSendsAfterDelay() {
+ Handler handler = spy(new Handler(mTestableLooper.getLooper()));
+ InOrder inOrder = inOrder(handler);
+
+ final Message messageA = handler.obtainMessage(1);
+ final Message messageB = handler.obtainMessage(2);
+ final Message messageC = handler.obtainMessage(3);
+
+ handler.sendMessageDelayed(messageA, 0);
+ handler.sendMessageDelayed(messageB, 0);
+ handler.sendMessageDelayed(messageC, 500);
+
+ mTestableLooper.moveTimeForward(500);
+ mTestableLooper.processAllMessages();
+
+ inOrder.verify(handler).dispatchMessage(messageA);
+ inOrder.verify(handler).dispatchMessage(messageB);
+ inOrder.verify(handler).dispatchMessage(messageC);
+ }
+
}