summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt11
-rw-r--r--api/system-current.txt11
-rw-r--r--api/test-current.txt43
-rw-r--r--cmds/screencap/screencap.cpp3
-rw-r--r--cmds/statsd/Android.mk4
-rw-r--r--cmds/statsd/src/AnomalyMonitor.cpp111
-rw-r--r--cmds/statsd/src/AnomalyMonitor.h129
-rw-r--r--cmds/statsd/src/DropboxReader.cpp41
-rw-r--r--cmds/statsd/src/DropboxReader.h10
-rw-r--r--cmds/statsd/src/DropboxWriter.cpp30
-rw-r--r--cmds/statsd/src/DropboxWriter.h13
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp23
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h6
-rw-r--r--cmds/statsd/src/indexed_priority_queue.h195
-rw-r--r--cmds/statsd/src/parse_util.cpp113
-rw-r--r--cmds/statsd/src/parse_util.h28
-rw-r--r--cmds/statsd/src/stats_constants.proto19
-rw-r--r--cmds/statsd/src/stats_log.proto86
-rw-r--r--cmds/statsd/src/statsd_config.proto448
-rw-r--r--cmds/statsd/tests/indexed_priority_queue_test.cpp188
-rw-r--r--config/compiled-classes-phone1
-rw-r--r--config/preloaded-classes3
-rw-r--r--core/java/android/accounts/AbstractAccountAuthenticator.java3
-rw-r--r--core/java/android/accounts/AccountManager.java4
-rw-r--r--core/java/android/app/ActivityManager.java39
-rw-r--r--core/java/android/app/ActivityOptions.java51
-rw-r--r--core/java/android/app/IActivityManager.aidl15
-rw-r--r--core/java/android/app/VrManager.java20
-rw-r--r--core/java/android/app/WindowConfiguration.java14
-rw-r--r--core/java/android/content/Context.java7
-rw-r--r--core/java/android/content/Intent.java21
-rw-r--r--core/java/android/content/pm/ActivityInfo.java48
-rw-r--r--core/java/android/content/res/Configuration.java27
-rw-r--r--core/java/android/hardware/location/NanoAppInstanceInfo.java4
-rw-r--r--core/java/android/net/metrics/WakeupStats.java6
-rw-r--r--core/java/android/os/IStatsCompanionService.aidl44
-rw-r--r--core/java/android/os/StrictMode.java58
-rwxr-xr-xcore/java/android/provider/Settings.java5
-rw-r--r--core/java/android/view/Surface.java2
-rw-r--r--core/java/android/view/WindowManagerPolicy.java62
-rw-r--r--core/java/android/view/autofill/AutofillManager.java118
-rw-r--r--core/java/android/view/autofill/IAutoFillManagerClient.aidl10
-rw-r--r--core/java/android/webkit/WebViewFactory.java4
-rw-r--r--core/java/android/webkit/WebViewZygote.java19
-rw-r--r--core/java/android/widget/RemoteViews.java11
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/java/com/android/internal/app/NightDisplayController.java150
-rw-r--r--core/java/com/android/internal/os/Zygote.java5
-rw-r--r--core/res/AndroidManifest.xml19
-rw-r--r--core/res/res/layout/autofill_save.xml7
-rw-r--r--core/tests/coretests/src/android/database/DatabaseGeneralTest.java31
-rw-r--r--core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java80
-rw-r--r--core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py26
-rw-r--r--core/tests/coretests/src/android/net/LinkPropertiesTest.java8
-rw-r--r--libs/hwui/VectorDrawable.h10
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp49
-rw-r--r--media/java/android/media/MediaCodecInfo.java4
-rw-r--r--media/java/android/media/MediaRouter.java6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java70
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java98
-rw-r--r--packages/SettingsProvider/res/values-af/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-am/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ar/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-az/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-be/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-bg/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-bn/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-bs/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ca/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-cs/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-da/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-de/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-el/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-en-rAU/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-en-rCA/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-en-rGB/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-en-rIN/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-en-rXC/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-es-rUS/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-es/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-et/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-eu/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-fa/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-fi/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-fr-rCA/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-fr/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-gl/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-gu/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-hi/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-hr/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-hu/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-hy/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-in/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-is/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-it/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-iw/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ja/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ka/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-kk/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-km/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-kn/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ko/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ky/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-lo/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-lt/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-lv/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-mk/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ml/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-mn/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-mr/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ms/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-my/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-nb/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ne/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-nl/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-pa/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-pl/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-pt-rBR/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-pt-rPT/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-pt/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ro/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ru/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-si/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-sk/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-sl/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-sq/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-sr/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-sv/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-sw/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ta/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-te/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-th/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-tl/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-tr/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-uk/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-ur/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-uz/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-vi/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-zh-rCN/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-zh-rHK/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-zh-rTW/defaults.xml1
-rw-r--r--packages/SettingsProvider/res/values-zu/defaults.xml1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java5
-rw-r--r--proto/src/ipconnectivity.proto4
-rw-r--r--proto/src/metrics_constants.proto76
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java2
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java8
-rw-r--r--services/autofill/java/com/android/server/autofill/Helper.java13
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java5
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java196
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java66
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java136
-rw-r--r--services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java6
-rw-r--r--services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java36
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java11
-rw-r--r--services/backup/java/com/android/server/backup/internal/PerformBackupTask.java3
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java3
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java3
-rw-r--r--services/backup/java/com/android/server/backup/utils/AppBackupUtils.java5
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java1214
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java244
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java31
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java15
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java377
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java98
-rw-r--r--services/core/java/com/android/server/am/KeyguardController.java30
-rw-r--r--services/core/java/com/android/server/am/LockTaskController.java5
-rw-r--r--services/core/java/com/android/server/am/TaskPersister.java3
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java28
-rw-r--r--services/core/java/com/android/server/am/UserController.java200
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java6
-rw-r--r--services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java2
-rw-r--r--services/core/java/com/android/server/connectivity/NetdEventListenerService.java4
-rw-r--r--services/core/java/com/android/server/display/NightDisplayService.java101
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java16
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java16
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java14
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java297
-rw-r--r--services/core/java/com/android/server/policy/WindowOrientationListener.java8
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java46
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java30
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java165
-rw-r--r--services/core/java/com/android/server/timezone/IntentHelper.java21
-rw-r--r--services/core/java/com/android/server/timezone/IntentHelperImpl.java40
-rw-r--r--services/core/java/com/android/server/timezone/PackageTracker.java58
-rw-r--r--services/core/java/com/android/server/timezone/RulesManagerService.java24
-rw-r--r--services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java100
-rw-r--r--services/core/java/com/android/server/twilight/TwilightState.java23
-rw-r--r--services/core/java/com/android/server/webkit/SystemImpl.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java9
-rw-r--r--services/core/java/com/android/server/wm/StackWindowController.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java3
-rw-r--r--services/java/com/android/server/SystemServer.java45
-rw-r--r--services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java47
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java110
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java2
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java5
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java185
-rw-r--r--telephony/java/com/android/ims/ImsCallProfile.java55
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/SmsMessage.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java8
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SmsMessage.java4
-rw-r--r--tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java4
-rw-r--r--tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java4
-rw-r--r--tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java4
238 files changed, 4487 insertions, 3089 deletions
diff --git a/Android.mk b/Android.mk
index 7bb64482df73..aa7caa547e43 100644
--- a/Android.mk
+++ b/Android.mk
@@ -270,6 +270,7 @@ LOCAL_SRC_FILES += \
core/java/android/os/IRecoverySystemProgressListener.aidl \
core/java/android/os/IRemoteCallback.aidl \
core/java/android/os/ISchedulingPolicyService.aidl \
+ core/java/android/os/IStatsCompanionService.aidl \
core/java/android/os/IStatsManager.aidl \
core/java/android/os/IThermalEventListener.aidl \
core/java/android/os/IThermalService.aidl \
diff --git a/api/current.txt b/api/current.txt
index d7e1a7a6bb0e..f6410834f257 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39997,8 +39997,10 @@ package android.telephony {
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
method public static void addTtsSpan(android.text.Spannable, int, int);
- method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
- method public static java.lang.String calledPartyBCDToString(byte[], int, int);
+ method public static deprecated java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
+ method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int, int);
+ method public static deprecated java.lang.String calledPartyBCDToString(byte[], int, int);
+ method public static java.lang.String calledPartyBCDToString(byte[], int, int, int);
method public static boolean compare(java.lang.String, java.lang.String);
method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
@@ -40031,12 +40033,15 @@ package android.telephony {
method public static byte[] networkPortionToCalledPartyBCD(java.lang.String);
method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String);
method public static java.lang.String normalizeNumber(java.lang.String);
- method public static byte[] numberToCalledPartyBCD(java.lang.String);
+ method public static deprecated byte[] numberToCalledPartyBCD(java.lang.String);
+ method public static byte[] numberToCalledPartyBCD(java.lang.String, int);
method public static java.lang.String replaceUnicodeDigits(java.lang.String);
method public static java.lang.String stringFromStringAndTOA(java.lang.String, int);
method public static java.lang.String stripSeparators(java.lang.String);
method public static java.lang.String toCallerIDMinMatch(java.lang.String);
method public static int toaFromString(java.lang.String);
+ field public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; // 0x2
+ field public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; // 0x1
field public static final int FORMAT_JAPAN = 2; // 0x2
field public static final int FORMAT_NANP = 1; // 0x1
field public static final int FORMAT_UNKNOWN = 0; // 0x0
diff --git a/api/system-current.txt b/api/system-current.txt
index 4f4b9db1b43a..eee24dea55dc 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -43472,8 +43472,10 @@ package android.telephony {
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
method public static void addTtsSpan(android.text.Spannable, int, int);
- method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
- method public static java.lang.String calledPartyBCDToString(byte[], int, int);
+ method public static deprecated java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
+ method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int, int);
+ method public static deprecated java.lang.String calledPartyBCDToString(byte[], int, int);
+ method public static java.lang.String calledPartyBCDToString(byte[], int, int, int);
method public static boolean compare(java.lang.String, java.lang.String);
method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
@@ -43506,12 +43508,15 @@ package android.telephony {
method public static byte[] networkPortionToCalledPartyBCD(java.lang.String);
method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String);
method public static java.lang.String normalizeNumber(java.lang.String);
- method public static byte[] numberToCalledPartyBCD(java.lang.String);
+ method public static deprecated byte[] numberToCalledPartyBCD(java.lang.String);
+ method public static byte[] numberToCalledPartyBCD(java.lang.String, int);
method public static java.lang.String replaceUnicodeDigits(java.lang.String);
method public static java.lang.String stringFromStringAndTOA(java.lang.String, int);
method public static java.lang.String stripSeparators(java.lang.String);
method public static java.lang.String toCallerIDMinMatch(java.lang.String);
method public static int toaFromString(java.lang.String);
+ field public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; // 0x2
+ field public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; // 0x1
field public static final int FORMAT_JAPAN = 2; // 0x2
field public static final int FORMAT_NANP = 1; // 0x1
field public static final int FORMAT_UNKNOWN = 0; // 0x0
diff --git a/api/test-current.txt b/api/test-current.txt
index 7256e5cf1cf9..2d7f67fe1650 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4052,10 +4052,11 @@ package android.app {
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public void requestUsageTimeReport(android.app.PendingIntent);
method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
+ method public void setLaunchActivityType(int);
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
method public android.app.ActivityOptions setLaunchDisplayId(int);
- method public void setLaunchStackId(int);
method public void setLaunchTaskId(int);
+ method public void setLaunchWindowingMode(int);
method public void setTaskOverlay(boolean, boolean);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
@@ -6244,6 +6245,7 @@ package android.app {
field public static final int ACTIVITY_TYPE_UNDEFINED = 0; // 0x0
field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5
field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1
+ field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4
field public static final int WINDOWING_MODE_PINNED = 2; // 0x2
field public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3; // 0x3
field public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4; // 0x4
@@ -31816,7 +31818,7 @@ package android.os {
method public static android.os.StrictMode.VmPolicy getVmPolicy();
method public static void noteSlowCall(java.lang.String);
method public static void setThreadPolicy(android.os.StrictMode.ThreadPolicy);
- method public static void setViolationListener(android.os.StrictMode.ViolationListener);
+ method public static void setViolationLogger(android.os.StrictMode.ViolationLogger);
method public static void setVmPolicy(android.os.StrictMode.VmPolicy);
}
@@ -31850,8 +31852,30 @@ package android.os {
method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
}
- public static abstract interface StrictMode.ViolationListener {
- method public abstract void onViolation(java.lang.String);
+ public static final class StrictMode.ViolationInfo implements android.os.Parcelable {
+ ctor public StrictMode.ViolationInfo();
+ ctor public StrictMode.ViolationInfo(java.lang.Throwable, int);
+ ctor public StrictMode.ViolationInfo(java.lang.String, java.lang.Throwable, int);
+ ctor public StrictMode.ViolationInfo(android.os.Parcel);
+ ctor public StrictMode.ViolationInfo(android.os.Parcel, boolean);
+ method public int describeContents();
+ method public void dump(android.util.Printer, java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.os.StrictMode.ViolationInfo> CREATOR;
+ field public java.lang.String broadcastIntentAction;
+ field public final android.app.ApplicationErrorReport.CrashInfo crashInfo;
+ field public int durationMillis;
+ field public final java.lang.String message;
+ field public int numAnimationsRunning;
+ field public long numInstances;
+ field public final int policy;
+ field public java.lang.String[] tags;
+ field public int violationNumThisLoop;
+ field public long violationUptimeMillis;
+ }
+
+ public static abstract interface StrictMode.ViolationLogger {
+ method public abstract void log(android.os.StrictMode.ViolationInfo);
}
public static final class StrictMode.VmPolicy {
@@ -40306,8 +40330,10 @@ package android.telephony {
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
method public static void addTtsSpan(android.text.Spannable, int, int);
- method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
- method public static java.lang.String calledPartyBCDToString(byte[], int, int);
+ method public static deprecated java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
+ method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int, int);
+ method public static deprecated java.lang.String calledPartyBCDToString(byte[], int, int);
+ method public static java.lang.String calledPartyBCDToString(byte[], int, int, int);
method public static boolean compare(java.lang.String, java.lang.String);
method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
@@ -40340,12 +40366,15 @@ package android.telephony {
method public static byte[] networkPortionToCalledPartyBCD(java.lang.String);
method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String);
method public static java.lang.String normalizeNumber(java.lang.String);
- method public static byte[] numberToCalledPartyBCD(java.lang.String);
+ method public static deprecated byte[] numberToCalledPartyBCD(java.lang.String);
+ method public static byte[] numberToCalledPartyBCD(java.lang.String, int);
method public static java.lang.String replaceUnicodeDigits(java.lang.String);
method public static java.lang.String stringFromStringAndTOA(java.lang.String, int);
method public static java.lang.String stripSeparators(java.lang.String);
method public static java.lang.String toCallerIDMinMatch(java.lang.String);
method public static int toaFromString(java.lang.String);
+ field public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; // 0x2
+ field public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; // 0x1
field public static final int FORMAT_JAPAN = 2; // 0x2
field public static final int FORMAT_NANP = 1; // 0x1
field public static final int FORMAT_UNKNOWN = 0; // 0x0
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 35f8bbb57e50..6ded24648353 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -101,9 +101,6 @@ static uint32_t dataSpaceToInt(android_dataspace d)
static status_t notifyMediaScanner(const char* fileName) {
String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
- String8 fileUrl("\"");
- fileUrl.append(fileName);
- fileUrl.append("\"");
cmd.append(fileName);
cmd.append(" > /dev/null");
int result = system(cmd.string());
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index f1b3c053b2cb..6de530319727 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -41,11 +41,14 @@ LOCAL_MODULE := statsd
LOCAL_SRC_FILES := \
../../core/java/android/os/IStatsManager.aidl \
+ ../../core/java/android/os/IStatsCompanionService.aidl \
src/StatsService.cpp \
+ src/AnomalyMonitor.cpp \
src/LogEntryPrinter.cpp \
src/LogReader.cpp \
src/main.cpp \
src/DropboxWriter.cpp \
+ src/parse_util.cpp \
src/StatsLogProcessor.cpp \
src/stats_log.proto \
src/statsd_config.proto \
@@ -118,6 +121,7 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \
LOCAL_SRC_FILES := \
../../core/java/android/os/IStatsManager.aidl \
src/StatsService.cpp \
+ tests/indexed_priority_queue_test.cpp \
src/LogEntryPrinter.cpp \
src/LogReader.cpp \
tests/LogReader_test.cpp \
diff --git a/cmds/statsd/src/AnomalyMonitor.cpp b/cmds/statsd/src/AnomalyMonitor.cpp
new file mode 100644
index 000000000000..d73de957881a
--- /dev/null
+++ b/cmds/statsd/src/AnomalyMonitor.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define LOG_TAG "AnomalyMonitor"
+#define DEBUG true
+
+#include <AnomalyMonitor.h>
+
+#include <binder/IServiceManager.h>
+#include <cutils/log.h>
+
+namespace statsd {
+
+AnomalyMonitor::AnomalyMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec)
+ : mRegisteredAlarmTimeSec(0),
+ mMinUpdateTimeSec(minDiffToUpdateRegisteredAlarmTimeSec) {
+}
+
+AnomalyMonitor::~AnomalyMonitor() {
+}
+
+void AnomalyMonitor::add(sp<const AnomalyAlarm> alarm) {
+ if (alarm == nullptr) {
+ ALOGW("Asked to add a null alarm.");
+ return;
+ }
+ if (alarm->timestampSec < 1) {
+ // forbidden since a timestamp 0 is used to indicate no alarm registered
+ ALOGW("Asked to add a 0-time alarm.");
+ return;
+ }
+ std::lock_guard<std::mutex> lock(mLock);
+ // TODO: Ensure that refractory period is respected.
+ if (DEBUG) ALOGD("Adding alarm with time %u", alarm->timestampSec);
+ mPq.push(alarm);
+ if (mRegisteredAlarmTimeSec < 1 ||
+ alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) {
+ updateRegisteredAlarmTime(alarm->timestampSec);
+ }
+}
+
+void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) {
+ if (alarm == nullptr) {
+ ALOGW("Asked to remove a null alarm.");
+ return;
+ }
+ std::lock_guard<std::mutex> lock(mLock);
+ if (DEBUG) ALOGD("Removing alarm with time %u", alarm->timestampSec);
+ mPq.remove(alarm);
+ if (mPq.empty()) {
+ if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
+ mRegisteredAlarmTimeSec = 0;
+ // TODO: Make this resistant to doing work when companion is not ready yet
+ sp<IStatsCompanionService> statsCompanionService = getStatsCompanion_l();
+ if (statsCompanionService != nullptr) {
+ statsCompanionService->cancelAnomalyAlarm();
+ }
+ return;
+ }
+ uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec;
+ if (DEBUG) ALOGD("Soonest alarm is %u", soonestAlarmTimeSec);
+ if (soonestAlarmTimeSec > mRegisteredAlarmTimeSec + mMinUpdateTimeSec) {
+ updateRegisteredAlarmTime(soonestAlarmTimeSec);
+ }
+}
+
+void AnomalyMonitor::updateRegisteredAlarmTime(uint32_t timestampSec) {
+ if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec);
+ mRegisteredAlarmTimeSec = timestampSec;
+ sp<IStatsCompanionService> statsCompanionService = getStatsCompanion_l();
+ if (statsCompanionService != nullptr) {
+ statsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec));
+ }
+}
+
+sp<IStatsCompanionService> AnomalyMonitor::getStatsCompanion_l() {
+ if (mStatsCompanion != nullptr) {
+ return mStatsCompanion;
+ }
+ // Get statscompanion service from service manager
+ const sp<IServiceManager> sm(defaultServiceManager());
+ if (sm != nullptr) {
+ const String16 name("statscompanion");
+ mStatsCompanion =
+ interface_cast<IStatsCompanionService>(sm->checkService(name));
+ if (mStatsCompanion == nullptr) {
+ ALOGW("statscompanion service unavailable!");
+ return nullptr;
+ }
+ }
+ return mStatsCompanion;
+}
+
+int64_t AnomalyMonitor::secToMs(uint32_t timeSec) {
+ return ((int64_t) timeSec) * 1000;
+}
+
+} // namespace statsd \ No newline at end of file
diff --git a/cmds/statsd/src/AnomalyMonitor.h b/cmds/statsd/src/AnomalyMonitor.h
new file mode 100644
index 000000000000..5418cf0dc552
--- /dev/null
+++ b/cmds/statsd/src/AnomalyMonitor.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANOMALY_MONITOR_H
+#define ANOMALY_MONITOR_H
+
+#include <indexed_priority_queue.h>
+#include <android/os/IStatsCompanionService.h>
+#include <utils/RefBase.h>
+
+#include <queue>
+#include <vector>
+
+using namespace android::os;
+using namespace android;
+
+namespace statsd {
+
+/**
+ * Represents an alarm, associated with some aggregate metric, holding a
+ * projected time at which the metric is expected to exceed its anomaly
+ * threshold.
+ * Timestamps are in seconds since epoch in a uint32, so will fail in year 2106.
+ */
+struct AnomalyAlarm : public RefBase {
+ AnomalyAlarm(uint32_t timestampSec) : timestampSec(timestampSec) {
+ }
+
+ const uint32_t timestampSec;
+
+ /** AnomalyAlarm a is smaller (higher priority) than b if its timestamp is sooner. */
+ struct SmallerTimestamp {
+ bool operator()(sp<const AnomalyAlarm> a, sp<const AnomalyAlarm> b) const {
+ return (a->timestampSec < b->timestampSec);
+ }
+ };
+};
+
+/**
+ * Manages alarms for Anomaly Detection.
+ */
+class AnomalyMonitor {
+ public:
+ /**
+ * @param minDiffToUpdateRegisteredAlarmTimeSec If the soonest alarm differs
+ * from the registered alarm by more than this amount, update the registered
+ * alarm.
+ */
+ AnomalyMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec);
+ ~AnomalyMonitor();
+
+ /**
+ * Adds the given alarm (reference) to the queue.
+ */
+ void add(sp<const AnomalyAlarm> alarm);
+
+ /**
+ * Removes the given alarm (reference) from the queue.
+ * Note that alarm comparison is reference-based; if another alarm exists
+ * with the same timestampSec, that alarm will still remain in the queue.
+ */
+ void remove(sp<const AnomalyAlarm> alarm);
+
+ /**
+ * Returns the projected alarm timestamp that is registered with
+ * StatsCompanionService. This may not be equal to the soonest alarm,
+ * but should be within minDiffToUpdateRegisteredAlarmTimeSec of it.
+ */
+ uint32_t getRegisteredAlarmTimeSec() const {
+ return mRegisteredAlarmTimeSec;
+ }
+
+ private:
+ /** Lock for accessing/writing to mPq. */
+ std::mutex mLock;
+
+ /**
+ * Timestamp (seconds since epoch) of the alarm registered with
+ * StatsCompanionService. This, in general, may not be equal to the soonest
+ * alarm stored in mPq, but should be within minUpdateTimeSec of it.
+ * A value of 0 indicates that no alarm is currently registered.
+ */
+ uint32_t mRegisteredAlarmTimeSec;
+
+ /**
+ * Priority queue of alarms, prioritized by soonest alarm.timestampSec.
+ */
+ indexed_priority_queue<AnomalyAlarm, AnomalyAlarm::SmallerTimestamp> mPq;
+
+ /**
+ * Binder interface for communicating with StatsCompanionService.
+ */
+ sp<IStatsCompanionService> mStatsCompanion;
+
+ /**
+ * Amount by which the soonest projected alarm must differ from
+ * mRegisteredAlarmTimeSec before updateRegisteredAlarmTime is called.
+ */
+ uint32_t mMinUpdateTimeSec;
+
+ /**
+ * Updates the alarm registered with StatsCompanionService to the given time.
+ * Also correspondingly updates mRegisteredAlarmTimeSec.
+ */
+ void updateRegisteredAlarmTime(uint32_t timestampSec);
+
+ /** Returns the StatsCompanionService. */
+ sp<IStatsCompanionService> getStatsCompanion_l();
+
+ /** Converts uint32 timestamp in seconds to a Java long in msec. */
+ int64_t secToMs(uint32_t timeSec);
+};
+
+} // namespace statsd
+
+#endif // ANOMALY_MONITOR_H \ No newline at end of file
diff --git a/cmds/statsd/src/DropboxReader.cpp b/cmds/statsd/src/DropboxReader.cpp
index 187f4ada61ca..cda2f431e435 100644
--- a/cmds/statsd/src/DropboxReader.cpp
+++ b/cmds/statsd/src/DropboxReader.cpp
@@ -15,9 +15,7 @@
*/
#include <android/os/DropBoxManager.h>
#include <android-base/file.h>
-#include <cutils/log.h>
#include <androidfw/ZipUtils.h>
-#include <stdio.h>
#include "DropboxReader.h"
@@ -25,14 +23,14 @@ using android::sp;
using android::String16;
using android::binder::Status;
using android::base::unique_fd;
+using android::os::statsd::EventMetricData;
using android::os::DropBoxManager;
-using android::os::statsd::StatsLogEntry;
using android::ZipUtils;
using std::vector;
status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) {
sp<DropBoxManager> dropbox = new DropBoxManager();
- StatsLogList logList;
+ StatsLogReport logReport;
long timestamp = msec;
// instead of while(true), put a hard limit 1000. Dropbox won't have more than 1000 files.
@@ -51,23 +49,23 @@ status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) {
timestamp = entry.getTimestamp();
if (entry.getFlags() & DropBoxManager::IS_GZIPPED) {
- if (!parseFromGzipFile(fd, logList)) {
+ if (!parseFromGzipFile(fd, logReport)) {
// Failed to parse from the file. Continue to fetch the next entry.
continue;
}
} else {
- if (!parseFromFile(fd, logList)) {
+ if (!parseFromFile(fd, logReport)) {
// Failed to parse from the file. Continue to fetch the next entry.
continue;
}
}
- printLog(out, logList);
+ printLog(out, logReport);
}
return android::OK;
}
-bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
+bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport) {
FILE *file = fdopen(fd, "r");
bool result = false;
bool scanResult;
@@ -80,7 +78,7 @@ bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
if (scanResult && method == kCompressDeflated) {
vector<uint8_t> buf(uncompressedLen);
if (ZipUtils::inflateToBuffer(file, &buf[0], uncompressedLen, compressedLen)) {
- if (list.ParseFromArray(&buf[0], uncompressedLen)) {
+ if (logReport.ParseFromArray(&buf[0], uncompressedLen)) {
result = true;
}
}
@@ -92,29 +90,30 @@ bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
}
// parse a non zipped file.
-bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogList& list) {
+bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogReport& logReport) {
string content;
if (!android::base::ReadFdToString(fd, &content)) {
ALOGE("Failed to read file");
return false;
}
- if (!list.ParseFromString(content)) {
+ if (!logReport.ParseFromString(content)) {
ALOGE("failed to parse log entry from data");
return false;
}
return true;
}
-void DropboxReader::printLog(FILE* out, const StatsLogList& list) {
- for (int i = 0; i < list.stats_log_entry_size(); i++) {
- const StatsLogEntry entry = list.stats_log_entry(i);
- // TODO: print pretty
- fprintf(out, "time_msec=%lld, type=%d, aggregate_type=%d, uid=%d, pid=%d ",
- entry.start_report_millis(), entry.type(), entry.aggregate_type(),
- entry.uid(), entry.pid());
- for (int j = 0; j < entry.pairs_size(); j++) {
- fprintf(out, "msg=%s ", entry.pairs(j).value_str().c_str());
+void DropboxReader::printLog(FILE* out, const StatsLogReport& logReport) {
+ fprintf(out, "start_time_msec=%lld, end_time_msec=%lld, ",
+ logReport.start_report_millis(), logReport.end_report_millis());
+ for (int i = 0; i < logReport.event_metrics().data_size(); i++) {
+ EventMetricData eventMetricData = logReport.event_metrics().data(i);
+ for (int j = 0; j < eventMetricData.key_value_pair_size(); j++) {
+ fprintf(out, "key=%d, ", eventMetricData.key_value_pair(j).key());
+ fprintf(out, "value_str=%s ", eventMetricData.key_value_pair(j).value_str().c_str());
+ fprintf(out, "value_int=%lld ", eventMetricData.key_value_pair(j).value_int());
+ fprintf(out, "value_float=%f ", eventMetricData.key_value_pair(j).value_float());
}
- fprintf(out, "\n");
}
+ fprintf(out, "\n");
}
diff --git a/cmds/statsd/src/DropboxReader.h b/cmds/statsd/src/DropboxReader.h
index a62ffde6b255..f7d5a8205f57 100644
--- a/cmds/statsd/src/DropboxReader.h
+++ b/cmds/statsd/src/DropboxReader.h
@@ -23,7 +23,7 @@
#include <stdio.h>
using android::base::unique_fd;
-using android::os::statsd::StatsLogList;
+using android::os::statsd::StatsLogReport;
using android::status_t;
using std::string;
@@ -33,13 +33,13 @@ public:
static status_t readStatsLogs(FILE* out, const string& tag, long msec);
private:
- static bool parseFromFile(const unique_fd& fd, StatsLogList& list);
- static bool parseFromGzipFile(const unique_fd& fd, StatsLogList& list);
- static void printLog(FILE* out, const StatsLogList& list);
+ static bool parseFromFile(const unique_fd& fd, StatsLogReport& logReport);
+ static bool parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport);
+ static void printLog(FILE* out, const StatsLogReport& logReport);
enum {
kCompressStored = 0, // no compression
kCompressDeflated = 8, // standard deflate
};
};
-#endif //DROPBOX_READER_H \ No newline at end of file
+#endif //DROPBOX_READER_H
diff --git a/cmds/statsd/src/DropboxWriter.cpp b/cmds/statsd/src/DropboxWriter.cpp
index a251056d9e81..01a9eac317d8 100644
--- a/cmds/statsd/src/DropboxWriter.cpp
+++ b/cmds/statsd/src/DropboxWriter.cpp
@@ -15,7 +15,6 @@
*/
#include <android/os/DropBoxManager.h>
-#include <cutils/log.h>
#include "DropboxWriter.h"
@@ -26,36 +25,35 @@ using android::String16;
using std::vector;
DropboxWriter::DropboxWriter(const string& tag)
- : mTag(tag), mLogList(), mBufferSize(0) {
+ : mTag(tag), mLogReport(), mBufferSize(0) {
}
-void DropboxWriter::addEntry(const StatsLogEntry& entry) {
- flushIfNecessary(entry);
- StatsLogEntry* newEntry = mLogList.add_stats_log_entry();
- newEntry->CopyFrom(entry);
- mBufferSize += entry.ByteSize();
+void DropboxWriter::addStatsLogReport(const StatsLogReport& log) {
+ mLogReport = log;
+ flushIfNecessary(log);
+ mBufferSize += log.ByteSize();
}
-void DropboxWriter::flushIfNecessary(const StatsLogEntry& entry) {
- // The serialized size of the StatsLogList is approximately the sum of the serialized size of
- // every StatsLogEntry inside it.
- if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) {
- flush();
- }
+void DropboxWriter::flushIfNecessary(const StatsLogReport& log) {
+ // TODO: Decide to flush depending on the serialized size of the StatsLogReport.
+ // if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) {
+ // flush();
+ // }
+ flush();
}
void DropboxWriter::flush() {
// now we get an exact byte size of the output
- const int numBytes = mLogList.ByteSize();
+ const int numBytes = mLogReport.ByteSize();
vector<uint8_t> buffer(numBytes);
sp<DropBoxManager> dropbox = new DropBoxManager();
- mLogList.SerializeToArray(&buffer[0], numBytes);
+ mLogReport.SerializeToArray(&buffer[0], numBytes);
Status status = dropbox->addData(String16(mTag.c_str()), &buffer[0],
numBytes, 0 /* no flag */);
if (!status.isOk()) {
ALOGE("failed to write to dropbox");
//TODO: What to do if flush fails??
}
- mLogList.Clear();
+ mLogReport.Clear();
mBufferSize = 0;
}
diff --git a/cmds/statsd/src/DropboxWriter.h b/cmds/statsd/src/DropboxWriter.h
index 176ac8b944a7..31b3f2764bb9 100644
--- a/cmds/statsd/src/DropboxWriter.h
+++ b/cmds/statsd/src/DropboxWriter.h
@@ -20,8 +20,7 @@
#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
using std::string;
-using android::os::statsd::StatsLogEntry;
-using android::os::statsd::StatsLogList;
+using android::os::statsd::StatsLogReport;
class DropboxWriter {
public:
@@ -30,7 +29,7 @@ public:
*/
DropboxWriter(const string& tag);
- void addEntry(const StatsLogEntry& entry);
+ void addStatsLogReport(const StatsLogReport& log);
/* Request a flush to dropbox. */
void flush();
@@ -46,11 +45,11 @@ private:
const string mTag;
- /* StatsLogList is a wrapper for storing a list of StatsLogEntry */
- StatsLogList mLogList;
+ /* Data that was captured for a single metric over a given interval of time. */
+ StatsLogReport mLogReport;
/* Current *serialized* size of the logs kept in memory.
- To save computation, we will not calculate the size of the StatsLogList every time when a new
+ To save computation, we will not calculate the size of the StatsLogReport every time when a new
entry is added, which would recursively call ByteSize() on every log entry. Instead, we keep
the sum of all individual stats log entry sizes. The size of a proto is approximately the sum
of the size of all member protos.
@@ -59,7 +58,7 @@ private:
/* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush
the logs to dropbox if true. */
- void flushIfNecessary(const StatsLogEntry& entry);
+ void flushIfNecessary(const StatsLogReport& log);
};
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 5f5e216fe3a6..c2fffd8a2d84 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -16,14 +16,13 @@
#include <StatsLogProcessor.h>
-#include <log/event_tag_map.h>
-#include <log/logprint.h>
+#include <log/log_event_list.h>
#include <utils/Errors.h>
-#include <cutils/log.h>
-#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
+#include <parse_util.h>
using namespace android;
-using android::os::statsd::StatsLogEntry;
+using android::os::statsd::EventMetricData;
+using android::os::statsd::StatsLogReport;
StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs")
{
@@ -57,12 +56,12 @@ StatsLogProcessor::OnLogEvent(const log_msg& msg)
// dump all statsd logs to dropbox for now.
// TODO: Add filtering, aggregation, etc.
if (err == NO_ERROR) {
- StatsLogEntry logEntry;
- logEntry.set_uid(entry.uid);
- logEntry.set_pid(entry.pid);
- logEntry.set_start_report_millis(entry.tv_sec / 1000 + entry.tv_nsec / 1000 / 1000);
- logEntry.add_pairs()->set_value_str(entry.message, entry.messageLen);
- m_dropbox_writer.addEntry(logEntry);
+ StatsLogReport logReport;
+ logReport.set_start_report_millis(entry.tv_sec / 1000 + entry.tv_nsec / 1000 / 1000);
+ EventMetricData *eventMetricData = logReport.mutable_event_metrics()->add_data();
+ *eventMetricData = parse(msg);
+
+ m_dropbox_writer.addStatsLogReport(logReport);
}
}
@@ -71,4 +70,4 @@ StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config)
{
m_configs[config_source] = config;
ALOGD("Updated configuration for source %i", config_source);
-} \ No newline at end of file
+}
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index d2daecd541db..5df84245a406 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -16,12 +16,8 @@
#ifndef STATS_LOG_PROCESSOR_H
#define STATS_LOG_PROCESSOR_H
-#include "LogReader.h"
-#include "DropboxWriter.h"
+#include "parse_util.h"
-#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
-#include <log/logprint.h>
-#include <stdio.h>
#include <unordered_map>
using android::os::statsd::StatsdConfig;
diff --git a/cmds/statsd/src/indexed_priority_queue.h b/cmds/statsd/src/indexed_priority_queue.h
new file mode 100644
index 000000000000..d302f855b1bf
--- /dev/null
+++ b/cmds/statsd/src/indexed_priority_queue.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef STATSD_INDEXED_PRIORITY_QUEUE_H
+#define STATSD_INDEXED_PRIORITY_QUEUE_H
+
+// ALOGE can be called from this file. If header loaded by another class, use their LOG_TAG instead.
+#ifndef LOG_TAG
+#define LOG_TAG "statsd(indexed_priority_queue)"
+#endif //LOG_TAG
+
+#include <cutils/log.h>
+#include <unordered_map>
+#include <utils/RefBase.h>
+#include <vector>
+
+using namespace android;
+
+namespace statsd {
+
+/** Defines a hash function for sp<AA>, returning the hash of the underlying pointer. */
+template <class AA>
+struct SpHash {
+ size_t operator()(const sp<const AA>& k) const {
+ return std::hash<const AA*>()(k.get());
+ }
+};
+
+/**
+ * Min priority queue for generic type AA.
+ * Unlike a regular priority queue, this class is also capable of removing interior elements.
+ * @tparam Comparator must implement [bool operator()(sp<const AA> a, sp<const AA> b)], returning
+ * whether a should be closer to the top of the queue than b.
+ */
+template <class AA, class Comparator>
+class indexed_priority_queue {
+ public:
+ indexed_priority_queue();
+ /** Adds a into the priority queue. If already present or a==nullptr, does nothing. */
+ void push(sp<const AA> a);
+ /** Removes a from the priority queue. If not present or a==nullptr, does nothing. */
+ void remove(sp<const AA> a);
+ /** Removes all elements. */
+ void clear();
+ /** Returns whether priority queue contains a (not just a copy of a, but a itself). */
+ bool contains(sp<const AA> a) const;
+ /** Returns min element. Returns nullptr iff empty(). */
+ sp<const AA> top() const;
+ /** Returns number of elements in priority queue. */
+ size_t size() const { return pq.size() - 1; } // pq is 1-indexed
+ /** Returns true iff priority queue is empty. */
+ bool empty() const { return size() < 1; }
+
+ private:
+ /** Vector representing a min-heap (1-indexed, with nullptr at 0). */
+ std::vector<sp<const AA>> pq;
+ /** Mapping of each element in pq to its index in pq (i.e. the inverse of a=pq[i]). */
+ std::unordered_map<sp<const AA>, size_t, SpHash<AA>> indices;
+
+ void init();
+ void sift_up(size_t idx);
+ void sift_down(size_t idx);
+ /** Returns whether pq[idx1] is considered higher than pq[idx2], according to Comparator. */
+ bool higher(size_t idx1, size_t idx2) const;
+ void swap_indices(size_t i, size_t j);
+};
+
+// Implementation must be done in this file due to use of template.
+
+template <class AA, class Comparator>
+indexed_priority_queue<AA,Comparator>::indexed_priority_queue() {
+ init();
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::push(sp<const AA> a) {
+ if (a == nullptr) return;
+ if (contains(a)) return;
+ pq.push_back(a);
+ size_t idx = size(); // index of last element since 1-indexed
+ indices.insert({a, idx});
+ sift_up(idx); // get the pq back in order
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::remove(sp<const AA> a) {
+ if (a == nullptr) return;
+ if (!contains(a)) return;
+ size_t idx = indices[a];
+ if (idx >= pq.size()) {
+ ALOGE("indexed_priority_queue: Invalid index in map of indices.");
+ return;
+ }
+ if (idx == size()) { // if a is the last element, i.e. at index idx == size() == (pq.size()-1)
+ pq.pop_back();
+ indices.erase(a);
+ return;
+ }
+ // move last element (guaranteed not to be at idx) to idx, then delete a
+ sp<const AA> last_a = pq.back();
+ pq[idx] = last_a;
+ pq.pop_back();
+ indices[last_a] = idx;
+ indices.erase(a);
+
+ // get the heap back in order (since the element at idx is not in order)
+ sift_up(idx);
+ sift_down(idx);
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::clear() {
+ pq.clear();
+ indices.clear();
+ init();
+}
+
+template <class AA, class Comparator>
+sp<const AA> indexed_priority_queue<AA,Comparator>::top() const {
+ if (empty()) return nullptr;
+ return pq[1];
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::init() {
+ pq.push_back(nullptr); // so that pq is 1-indexed.
+ indices.insert({nullptr, 0}); // just to be consistent with pq.
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::sift_up(size_t idx) {
+ while (idx > 1) {
+ size_t parent = idx/2;
+ if (higher(idx, parent)) swap_indices(idx, parent);
+ else break;
+ idx = parent;
+ }
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::sift_down(size_t idx) {
+ while (2*idx <= size()) {
+ size_t child = 2 * idx;
+ if (child < size() && higher(child+1, child)) child++;
+ if (higher(child, idx)) swap_indices(child, idx);
+ else break;
+ idx = child;
+ }
+}
+
+template <class AA, class Comparator>
+bool indexed_priority_queue<AA,Comparator>::higher(size_t idx1, size_t idx2) const {
+ if (!(0u < idx1 && idx1 < pq.size() && 0u < idx2 && idx2 < pq.size())) {
+ ALOGE("indexed_priority_queue: Attempting to access invalid index");
+ return false; // got to do something.
+ }
+ return Comparator()(pq[idx1], pq[idx2]);
+}
+
+template <class AA, class Comparator>
+bool indexed_priority_queue<AA,Comparator>::contains(sp<const AA> a) const {
+ if (a == nullptr) return false; // publicly, we pretend that nullptr is not actually in pq.
+ return indices.count(a) > 0;
+}
+
+template <class AA, class Comparator>
+void indexed_priority_queue<AA,Comparator>::swap_indices(size_t i, size_t j) {
+ if (!(0u < i && i < pq.size() && 0u < j && j < pq.size())) {
+ ALOGE("indexed_priority_queue: Attempting to swap invalid index");
+ return;
+ }
+ sp<const AA> val_i = pq[i];
+ sp<const AA> val_j = pq[j];
+ pq[i] = val_j;
+ pq[j] = val_i;
+ indices[val_i] = j;
+ indices[val_j] = i;
+}
+
+} // namespace statsd
+
+#endif //STATSD_INDEXED_PRIORITY_QUEUE_H
diff --git a/cmds/statsd/src/parse_util.cpp b/cmds/statsd/src/parse_util.cpp
new file mode 100644
index 000000000000..9caeacf3b538
--- /dev/null
+++ b/cmds/statsd/src/parse_util.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <parse_util.h>
+#include <log/log_event_list.h>
+
+using android::os::statsd::EventMetricData;
+using android::os::statsd::KeyId;
+using android::os::statsd::KeyId_IsValid;
+using android::os::statsd::KeyValuePair;
+using android::os::statsd::TagId;
+using android::os::statsd::TagId_IsValid;
+
+EventMetricData parse(log_msg msg)
+{
+ // dump all statsd logs to dropbox for now.
+ // TODO: Add filtering, aggregation, etc.
+ EventMetricData eventMetricData;
+ android_log_context context = create_android_log_parser(const_cast<log_msg*>(&msg)->msg()
+ + sizeof(uint32_t),
+ const_cast<log_msg*>(&msg)->len()
+ - sizeof(uint32_t));
+ android_log_list_element elem;
+
+ if (context) {
+ memset(&elem, 0, sizeof(elem));
+ size_t index = 0;
+ int32_t key = -1;
+ int32_t tag = -1;
+
+ do {
+ elem = android_log_read_next(context);
+ switch ((int)elem.type) {
+ case EVENT_TYPE_INT:
+ if (index == 0) {
+ tag = elem.data.int32;
+ if (TagId_IsValid(tag)) {
+ eventMetricData.set_tag(static_cast<TagId>(tag));
+ } else {
+ break;
+ }
+ } else if (index % 2 == 1) {
+ key = elem.data.int32;
+ } else if (KeyId_IsValid(key)) {
+ int32_t val = elem.data.int32;
+ KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair();
+ keyValuePair->set_key(static_cast<KeyId>(key));
+ keyValuePair->set_value_int(val);
+ } else {
+ }
+ index++;
+ break;
+ case EVENT_TYPE_FLOAT:
+ if (index % 2 == 0 && KeyId_IsValid(key)) {
+ float val = elem.data.float32;
+ KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair();
+ keyValuePair->set_key(static_cast<KeyId>(key));
+ keyValuePair->set_value_float(val);
+ }
+ index++;
+ break;
+ case EVENT_TYPE_STRING:
+ if (index % 2 == 0 && KeyId_IsValid(key)) {
+ char* val = elem.data.string;
+ KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair();
+ keyValuePair->set_key(static_cast<KeyId>(key));
+ keyValuePair->set_value_str(val);
+ }
+ index++;
+ break;
+ case EVENT_TYPE_LONG:
+ if (index % 2 == 0 && KeyId_IsValid(key)) {
+ int64_t val = elem.data.int64;
+ KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair();
+ keyValuePair->set_key(static_cast<KeyId>(key));
+ keyValuePair->set_value_int(val);
+ }
+ index++;
+ break;
+ case EVENT_TYPE_LIST:
+ break;
+ case EVENT_TYPE_LIST_STOP:
+ break;
+ case EVENT_TYPE_UNKNOWN:
+ break;
+ default:
+ elem.complete = true;
+ break;
+ }
+
+ if (elem.complete) {
+ break;
+ }
+ } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
+
+ android_log_destroy(&context);
+ }
+
+ return eventMetricData;
+}
diff --git a/cmds/statsd/src/parse_util.h b/cmds/statsd/src/parse_util.h
new file mode 100644
index 000000000000..8750f822102d
--- /dev/null
+++ b/cmds/statsd/src/parse_util.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+#ifndef PARSE_UTIL_H
+#define PARSE_UTIL_H
+
+#include "LogReader.h"
+#include "DropboxWriter.h"
+
+#include <log/logprint.h>
+
+using android::os::statsd::EventMetricData;
+
+EventMetricData parse(const log_msg msg);
+
+#endif // PARSE_UTIL_H
diff --git a/cmds/statsd/src/stats_constants.proto b/cmds/statsd/src/stats_constants.proto
index 1787ae3cba2e..3f8bd1c5a9fc 100644
--- a/cmds/statsd/src/stats_constants.proto
+++ b/cmds/statsd/src/stats_constants.proto
@@ -22,10 +22,17 @@ option optimize_for = LITE_RUNTIME;
option java_package = "com.android.internal.logging";
option java_outer_classname = "StatsConstantsProto";
-message StatsConstants {
- // Event type.
- enum Type {
- WAKELOCK = 1;
- SCREEN= 2;
- }
+enum TagId {
+ WAKELOCK = 1;
+ SCREEN = 1003;
+}
+
+enum KeyId {
+ STATE = 1;
+ ANOTHER_STATE = 2;
+ EVENT_TIMESTAMP = 1001;
+ PACKAGE_NAME = 1002;
+ PACKAGE_VERSION = 1003;
+ PACKAGE_VERSION_STRING = 1004;
+ ATTRIBUTION_CHAIN = 1005;
}
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index ec92023c873a..2c66ded0c7ed 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -25,53 +25,53 @@ option java_outer_classname = "StatsLog";
import "frameworks/base/cmds/statsd/src/statsd_config.proto";
import "frameworks/base/cmds/statsd/src/stats_constants.proto";
-// StatsLogEntry is a generic proto holding a single metrics data.
-message StatsLogEntry {
- // Type of stats.
- optional android.os.statsd.StatsConstants.Type type = 1;
-
- // Aggregation type of the data.
- optional android.os.statsd.TrackedAggregateType aggregate_type = 2;
-
- // Start timestamp of the interval. Timestamp for event-type data will have
- // equal value for start_report_millis and end_report_millis.
- optional int64 start_report_millis = 3;
-
- // End timestamp of the interval.
- optional int64 end_report_millis = 4;
-
- // Package information for application-level data.
- optional string package_name = 5;
- optional int32 package_version = 6;
- optional string package_version_string = 7;
-
- // UID associated with the data.
- optional int32 uid = 8;
-
- // PID associated with the data.
- optional int32 pid = 9;
-
- // Payload contains key value pairs of the data from statsd.
- message KeyValuePair {
- // Integer representation of data type.
- optional int32 key = 1;
-
- oneof value {
- string value_str = 2;
- int64 value_int = 3;
- bool value_bool = 4;
- }
+message KeyValuePair {
+ optional KeyId key = 1;
+
+ oneof value {
+ string value_str = 2;
+ int64 value_int = 3;
+ bool value_bool = 4;
+ float value_float = 5;
}
- repeated KeyValuePair pairs = 10;
+}
+
+message EventMetricData {
+ optional TagId tag = 1;
+
+ repeated KeyValuePair key_value_pair = 2;
+}
- // Next tag: 11
+message CountBucketInfo {
+ optional int64 start_bucket_millis = 1;
+
+ optional int64 end_bucket_millis = 2;
+
+ optional int64 count = 3;
}
-// Data captured for a given metric during a given period of time.
-message StatsLogList {
- // Unique ID for this metric.
+message CountMetricData {
+ repeated KeyValuePair dimension = 1;
+
+ repeated CountBucketInfo bucket_info = 2;
+}
+
+message StatsLogReport {
optional int32 metric_id = 1;
- // List of stats log entry.
- repeated StatsLogEntry stats_log_entry = 2;
+ optional int64 start_report_millis = 2;
+
+ optional int64 end_report_millis = 3;
+
+ message EventMetricDataWrapper {
+ repeated EventMetricData data = 1;
+ }
+ message CountMetricDataWrapper {
+ repeated CountMetricData data = 1;
+ }
+
+ oneof data {
+ EventMetricDataWrapper event_metrics = 4;
+ CountMetricDataWrapper count_metrics = 5;
+ }
}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 2d034e50f4b5..c6119df691a3 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -1,40 +1,3 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-
-// Version 1.
-// Important: Update the version line above before copy-pasting this file
-// from/to Google3 and Android repository.
-// This proto needs to be manually synced between Google3 and Android versions.
-
-/*
- * Note about semantics of the buckets:
- * In this current proto scheme, the buckets are updated only when an event
- * occurs. In the case of durations, this means that we update at the end of a
- * duration.
- *
- * For example, suppose we have buckets at every 10 min:
- * 0, 10, 20, 30, 40, etc.
- * And then suppose a wakelock is first held starting at min 5 and lasts for 21
- * mins. Then the buckets for 0-10 and 10-20 don't contain anything and inside
- * the bucket for 20-30, we add the value of 21 minutes.
- *
- * Also note that buckets are only aligned to wall-clock (no custom time-bases).
- */
-
syntax = "proto2";
package android.os.statsd;
@@ -43,30 +6,21 @@ option optimize_for = LITE_RUNTIME;
option java_package = "com.android.internal.os";
option java_outer_classname = "StatsdConfigProto";
-// KeyMatcher specifies how to match the key.
-message KeyMatcher {
- oneof contents {
- int32 key = 1; // ID of the key to match.
+import "frameworks/base/cmds/statsd/src/stats_constants.proto";
- // Special matcher for package name. This will match either the package name
- // or the UID (statsD will map the UID of the source event to a package
- // name). Specify the package name to match in eq_string.
- bool use_package = 2;
- }
+message KeyMatcher {
+ optional KeyId key = 1;
+ optional bool as_package_name = 2 [ default = false ];
}
-// FieldMatcher allows us to match specific fields/keys in an event.
-message FieldMatcher {
+message KeyValueMatcher {
optional KeyMatcher key_matcher = 1;
oneof value_matcher {
- // Equality matchers
bool eq_bool = 2;
string eq_string = 3;
int32 eq_int32 = 4;
int64 eq_int64 = 5;
-
- // Numeric comparisons;
int32 lt_int32 = 6;
int32 gt_int32 = 7;
int64 lt_int64 = 8;
@@ -76,374 +30,90 @@ message FieldMatcher {
}
}
-enum OperationType {
+enum LogicalOperation {
AND = 1;
OR = 2;
- NOT = 3; // Must have only a single operand when using NOT operator.
- NAND = 4; // NAND and NOR as conveniences to avoid NOT+(AND/OR)-layers.
+ NOT = 3;
+ NAND = 4;
NOR = 5;
}
-enum TrackedAggregateType {
- // IS_RUNNING; // whether it is currently running
- VALUE_COUNT = 1; // count number of events
- VALUE_SUM = 2;
- VALUE_MAX = 3;
- VALUE_MIN = 4;
- DURATION_SUM = 5; // cumulative total time
- DURATION_MAX = 6; // longest continuously-on time
- DURATION_MIN = 7; // shortest continuously-on time
- //DURATION_CURRENT = 6; // current continuously-on time (not bucketed)
+message SimpleLogEntryMatcher {
+ repeated TagId tag = 1;
+
+ repeated KeyValueMatcher key_value_matcher = 2;
}
-// Assume the events come in with a tag and an array of (key, value) tuples
-// where the key must be an int32 and value can be any type.
-message LineMatcher {
- // For now, we assume that we don't flatten the tags (ie, one tag corresponds
- // to screen-on and screen-off events and key 1 represents ON or OFF).
- repeated int32 tag = 1; // Must match at least one of the tags.
+message LogEntryMatcher {
+ optional string name = 1;
- message Nested {
- optional OperationType operation = 1;
- repeated LineMatcher matcher = 2;
+ message Combination {
+ optional LogicalOperation operation = 1;
+ repeated LogEntryMatcher matcher = 2;
}
oneof contents {
- FieldMatcher requirement = 2;
- Nested nested = 3;
+ SimpleLogEntryMatcher simple_log_entry_matcher = 2;
+ Combination combination = 3;
}
}
-// Defines when an AggregateCounter or EventMatcher applies.
+message SimpleCondition {
+ optional string start = 1;
+
+ optional string stop = 2;
+
+ optional bool count_nesting = 3 [default = true];
+
+ optional string stop_all = 4;
+}
+
message Condition {
- message Nested {
- optional OperationType operation = 1;
- repeated Condition nested_conditions = 2; // operands that are themselves
- // conditions (recursively)
- }
+ optional string name = 1;
+
+ message Combination {
+ optional LogicalOperation operation = 1;
- // Leaf node of condition.
- message RangeMatcher {
- optional LineMatcher start = 1;
- optional LineMatcher stop = 2;
- optional bool count_nesting = 3
- [default = true]; // true if "start start stop" is still
- // considered running
-
- // Configure which fields define the slices. These fields must be present in
- // both the start and stop lines. Note that this can be a subset of all the
- // slices defined in the AggregateCounter.
- // For example, if the counter slices on both app name and wake lock name,
- // we can define that this range only slices on app name.
- repeated KeyMatcher slice = 4;
+ repeated string condition = 2;
}
oneof contents {
- RangeMatcher range = 1; // Represents a leaf node.
- Nested nested = 2; // Represents a non-leaf node.
+ SimpleCondition simple_condition = 2;
+ Combination combination = 3;
}
}
-// Emits matching events to statsd event buffer.
-message EventMatcher {
- // Tracks what configuration led to uploading of this event.
- optional int32 metric_id = 1;
+message Bucket {
+ optional int64 bucket_size_millis = 1;
+}
- // LineMatcher for the event to emit.
- optional LineMatcher what = 2;
+message EventMetric {
+ optional int64 metric_id = 1;
- optional Condition condition = 3;
+ optional string what = 2;
- // TODO: Have a clear use-case for this in P or-else drop this for P.
- message Filter {
- }
- optional Filter filter = 4;
+ optional string condition = 3;
}
-// Hard-code the possible metrics that we can pull.
-// For example, NETSTATS_BY_UID would provide network usage per uid.
-// We should treat the results like a batch of individual log events, and we
-// should process them one-by-one to re-use our LineMatcher logic.
-enum PulledMetricSource {
- NETSTATS = 1;
-}
+message CountMetric {
+ optional int64 metric_id = 1;
-message AggregateCounter { // previously called Timer
- // Specifies which fields in the message act as dimensions.
- // For both pushed and pulled metrics, we assume every record has all the
- // dimensions set.
- message Slicer {
- repeated KeyMatcher keys = 1;
- }
- optional Slicer slicer = 1;
-
- message ValueSource {
- message PushedMetric {
- // LineMatcher for the event to apply.
- // Slicing (which keys act as dimensions) should not be specified here.
- optional LineMatcher what = 1;
-
- // Only needed if one key should be treated as the value.
- optional int32 value_key = 2;
- }
-
- // The values for pulled metrics are computed and aggregated at the end of
- // the condition.
- message PulledMetric {
- optional bool compute_diff =
- 1; // If we want the diff (if this
- // metric is pulled when condition opens/closes).
- optional PulledMetricSource metric = 2;
-
- // We treat the pulled metrics as a batch of log-records that look like
- // they came from LogD.
- optional LineMatcher what = 3;
- optional int32 value_field = 4;
- }
-
- oneof value {
- PushedMetric pushed_metric = 1;
-
- // Pulled metrics are computed when the duration closes (and are also
- // fetched at the open if we need to compute a diff).
- // Pulled metrics require a condition being defined.
- // These metrics are not pulled at the end of every bucket.
- PulledMetric pulled_metric = 2;
-
- // Polled Metrics are pulled at the end of every bucket.
- // Since the buckets are only planned to be on wall-clock for Android P,
- // condition is NOT supported for polled metrics.
- PulledMetric polled_metric = 3;
- }
- }
- optional ValueSource value = 2;
-
- message TrackedAggregate {
- // Must be an integer that is uniquely chosen so we can identify the metric
- // on server. We will provide a tool on server to help generate this.
- optional int32 metric_id = 1;
-
- optional TrackedAggregateType type = 2;
-
- // Alert if the value, when summed over the Counter's number_of_buckets
- // most-recent bins, exceeds min_threshold or is below max_threshold. For
- // Anomaly Detection.
- message Alert {
- message IncidentdDetails {
- optional string
- alert_name = 1; // for humans and incidentd to identify this issue
- repeated int32 incidentd_sections = 2; // tells incidentd what to do if
- // alert triggers
- }
- optional IncidentdDetails incidentd_details = 1;
- optional int32 number_of_buckets = 2;
- // NOTE: that we assume the aggregate is only int.
- optional int64 trigger_if_gt = 3; // min threshold
- optional int64 trigger_if_lt = 4; // max_threshold;
- optional int32 refractory_period_secs = 5; // alarm cannot fire a second
- // time until elapsed
- }
- repeated Alert alerts = 3; // Support diff alert params for same aggregate.
- } // end TrackedAggregate
- repeated TrackedAggregate tracked_aggregates = 3;
-
- optional Condition condition = 4;
-
- message Bucket {
- // TODO: Consider switching to second granularity.
- // In practice, this must be chosen from a pre-defined list. So that we have
- // flexiblity, we don't hard-code this as an enum today.
- optional int64 bucket_size_msec = 1;
- optional int32 max_number_of_bits = 2; // Max bits per bucket.
- }
- optional Bucket bucket = 5;
+ optional string what = 2;
- message MiscellaneousEffect {
- optional LineMatcher matcher = 1; // When to trigger the effect
-
- enum Effect {
- STOP_ALL = 1; // Needed for stop-all events, where nested start value is
- // forced to 0.
- }
- repeated Effect effects = 2;
- } // end MiscellaneousEffect
- repeated MiscellaneousEffect misc_effects = 6;
-} // end Counter
-
-// Alarm configs not tied to a particular Counter.
-message GlobalAlertParameters {
- // No alarm can fire after any other alarm fired until this many seconds has
- // elapsed.
- optional int32 global_refractory_period_seconds = 1;
+ optional string condition = 3;
+
+ repeated KeyMatcher dimension = 4;
+
+ optional Bucket bucket = 5;
}
-// The config defining all metrics to be captured.
message StatsdConfig {
- // Event matchers.
- repeated EventMatcher event_matchers = 1;
+ optional int64 config_id = 1;
- // Aggregate counters.
- repeated AggregateCounter aggregate_counters = 2;
-}
+ repeated EventMetric event_metric = 2;
-/* Sample configurations start here:
-----Screen on time----
-AggregateCounter <
- condition <
- range <
- start <
- tag: SCREEN_ON
- requirement <
- key_matcher<
- key: SCREEN_ON_VALUE
- eq_bool: true
- stop <
- tag: SCREEN_ON
- requirement <
- key_matcher<
- key: SCREEN_ON_VALUE
- eq_bool: false
- metric_id: # set on server
- tracked_aggregates <
- DURATION_SUM
- (For brevity, omit the bucket options but they can also be set)
-
-----Screen off time----
-Should be like aboe but reversing start and stop
-
-----Log the screen change events----
-EventMatcher <
- metric_id: # set on server
- what <
- tag: SCREEN_ON
-
-----Number of crashes (across system)----
-AggregateCounter <
- metric_id: # set on server
- tracked_aggregates <
- VALUE_COUNT
- value <
- pushed_metric <
- what <
- tag: CRASH_TAG
-
-----Network Usage in bytes Per App While in Background----
-AggregateCounter <
- metric_id: # set on server
- slicer <
- keys <
- use_package_name: true
- tracked_aggregates <
- VALUE_SUM
- value <
- pulled_metric <
- compute_diff: true
- metric: Enum corresponding to network usage in bytes
- condition <
- range <
- sliced: true
- start <
- tag: APP_FOREGROUND_TRANSITION (assume false means move to background)
- requirement <
- key_matcher<
- key: APP_FOREGROUND_STATE
- eq_bool: false
- stop <
- tag: APP_FOREGROUND_TRANSITION (assume false means move to background)
- requirement <
- key_matcher<
- key: APP_FOREGROUND_STATE
- eq_bool: true
-
-----Wakelock Acquire time per app and wakelock
- while unplugged and screen off and in background process state----
-AggregateCounter <
- metric_id: # set on server
- slicer <
- keys <
- use_package_name: true
- keys <
- key: Key corresponding to wake_lock ID
- tracked_aggregates <
- DURATION_SUM
- condition <
- nested <
- operation: AND
- nested_conditions <
- range <
- start <
- tag: PLUGGED_IN (assume false means uncharged)
- requirement <
- key_matcher<
- key: PLUGGED_IN_STATE
- eq_bool: false
- stop <
- tag: PLUGGED_IN (assume false means uncharged)
- requirement <
- key_matcher<
- key: PLUGGED_IN_STATE
- eq_bool: true
- nested_conditions <
- range <
- start <
- tag: SCREEN_ON
- requirement <
- key_matcher<
- key: SCREEN_ON_STATE
- eq_bool: false
- stop <
- tag: SCREEN_ON
- requirement <
- key_matcher<
- key: SCREEN_ON_STATE
- eq_bool: true
- nested_conditions <
- range <
- start <
- tag: PROCESS_CHANGE
- requirement <
- key_matcher<
- key: PROCESS_STATE_VALUE
- eq_int32: BACKGROUND_PROCESS
- stop <
- tag: PROCESS_CHANGE
- nested <
- operation: NOT
- matcher< (This is an example of using the NOT to define stop)
- requirement < (Note this requirement should match the start.)
- key_matcher<
- key: PROCESS_STATE_VALUE
- eq_int32: BACKGROUND_PROCESS
- slice<
- use_package_name: true
-
-
-----Number of crashes (per app) ----
-AggregateCounter <
- metric_id: # set on server
- slicer <
- keys<
- use_package_name: true
- tracked_aggregates <
- VALUE_COUNT
- value <
- pushed_metric <
- what <
- tag: CRASH_TAG
-
----- Number of transitions to background (per app) ----
-AggregateCounter <
- metric_id: # set on server
- slicer <
- keys<
- use_package_name: true
- tracked_aggregates <
- VALUE_COUNT
- value <
- pushed_metric <
- what <
- tag: APP_FOREGROUND_TRANSITION
- requirement<
- key: APP_FOREGROUND_TRANSITION_STATE
- eq_bool: false
-
-*/
+ repeated CountMetric count_metric = 3;
+
+ repeated LogEntryMatcher log_entry_matcher = 4;
+
+ repeated Condition condition = 5;
+}
diff --git a/cmds/statsd/tests/indexed_priority_queue_test.cpp b/cmds/statsd/tests/indexed_priority_queue_test.cpp
new file mode 100644
index 000000000000..a679128dd37e
--- /dev/null
+++ b/cmds/statsd/tests/indexed_priority_queue_test.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "../src/indexed_priority_queue.h"
+
+#include <gtest/gtest.h>
+
+using namespace statsd;
+
+/** struct for template in indexed_priority_queue */
+struct AATest : public RefBase {
+ AATest(uint32_t val) : val(val) {
+ }
+
+ const int val;
+
+ struct Smaller {
+ bool operator()(const sp<const AATest> a, const sp<const AATest> b) const {
+ return (a->val < b->val);
+ }
+ };
+};
+
+#ifdef __ANDROID__
+TEST(indexed_priority_queue, empty_and_size) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+ sp<const AATest> aa4 = new AATest{4};
+ sp<const AATest> aa8 = new AATest{8};
+
+ EXPECT_EQ(0u, ipq.size());
+ EXPECT_TRUE(ipq.empty());
+
+ ipq.push(aa4);
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_FALSE(ipq.empty());
+
+ ipq.push(aa8);
+ EXPECT_EQ(2u, ipq.size());
+ EXPECT_FALSE(ipq.empty());
+
+ ipq.remove(aa4);
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_FALSE(ipq.empty());
+
+ ipq.remove(aa8);
+ EXPECT_EQ(0u, ipq.size());
+ EXPECT_TRUE(ipq.empty());
+}
+
+TEST(indexed_priority_queue, top) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+ sp<const AATest> aa2 = new AATest{2};
+ sp<const AATest> aa4 = new AATest{4};
+ sp<const AATest> aa8 = new AATest{8};
+ sp<const AATest> aa12 = new AATest{12};
+ sp<const AATest> aa16 = new AATest{16};
+ sp<const AATest> aa20 = new AATest{20};
+
+ EXPECT_EQ(ipq.top(), nullptr);
+
+ // add 8, 4, 12
+ ipq.push(aa8);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ ipq.push(aa12);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ ipq.push(aa4);
+ EXPECT_EQ(ipq.top(), aa4);
+
+ // remove 12, 4
+ ipq.remove(aa12);
+ EXPECT_EQ(ipq.top(), aa4);
+
+ ipq.remove(aa4);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ // add 16, 2, 20
+ ipq.push(aa16);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ ipq.push(aa2);
+ EXPECT_EQ(ipq.top(), aa2);
+
+ ipq.push(aa20);
+ EXPECT_EQ(ipq.top(), aa2);
+
+ // remove 2, 20, 16, 8
+ ipq.remove(aa2);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ ipq.remove(aa20);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ ipq.remove(aa16);
+ EXPECT_EQ(ipq.top(), aa8);
+
+ ipq.remove(aa8);
+ EXPECT_EQ(ipq.top(), nullptr);
+}
+
+TEST(indexed_priority_queue, push_same_aa) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+ sp<const AATest> aa4_a = new AATest{4};
+ sp<const AATest> aa4_b = new AATest{4};
+
+ ipq.push(aa4_a);
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_TRUE(ipq.contains(aa4_a));
+ EXPECT_FALSE(ipq.contains(aa4_b));
+
+ ipq.push(aa4_a);
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_TRUE(ipq.contains(aa4_a));
+ EXPECT_FALSE(ipq.contains(aa4_b));
+
+ ipq.push(aa4_b);
+ EXPECT_EQ(2u, ipq.size());
+ EXPECT_TRUE(ipq.contains(aa4_a));
+ EXPECT_TRUE(ipq.contains(aa4_b));
+}
+
+
+TEST(indexed_priority_queue, remove_nonexistant) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+ sp<const AATest> aa4 = new AATest{4};
+ sp<const AATest> aa5 = new AATest{5};
+
+ ipq.push(aa4);
+ ipq.remove(aa5);
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_TRUE(ipq.contains(aa4));
+ EXPECT_FALSE(ipq.contains(aa5));
+}
+
+TEST(indexed_priority_queue, remove_same_aa) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+ sp<const AATest> aa4_a = new AATest{4};
+ sp<const AATest> aa4_b = new AATest{4};
+
+ ipq.push(aa4_a);
+ ipq.push(aa4_b);
+ EXPECT_EQ(2u, ipq.size());
+ EXPECT_TRUE(ipq.contains(aa4_a));
+ EXPECT_TRUE(ipq.contains(aa4_b));
+
+ ipq.remove(aa4_b);
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_TRUE(ipq.contains(aa4_a));
+ EXPECT_FALSE(ipq.contains(aa4_b));
+
+ ipq.remove(aa4_a);
+ EXPECT_EQ(0u, ipq.size());
+ EXPECT_FALSE(ipq.contains(aa4_a));
+ EXPECT_FALSE(ipq.contains(aa4_b));
+}
+
+TEST(indexed_priority_queue, nulls) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+
+ EXPECT_TRUE(ipq.empty());
+ EXPECT_FALSE(ipq.contains(nullptr));
+
+ ipq.push(nullptr);
+ EXPECT_TRUE(ipq.empty());
+ EXPECT_FALSE(ipq.contains(nullptr));
+
+ ipq.remove(nullptr);
+ EXPECT_TRUE(ipq.empty());
+ EXPECT_FALSE(ipq.contains(nullptr));
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/config/compiled-classes-phone b/config/compiled-classes-phone
index c8297286b784..c1cbb648aae6 100644
--- a/config/compiled-classes-phone
+++ b/config/compiled-classes-phone
@@ -5243,7 +5243,6 @@ com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.NightDisplayController
com.android.internal.app.NightDisplayController$Callback
-com.android.internal.app.NightDisplayController$LocalTime
com.android.internal.app.ProcessMap
com.android.internal.app.ResolverActivity
com.android.internal.app.ToolbarActionBar
diff --git a/config/preloaded-classes b/config/preloaded-classes
index cd2965392c44..2844efb302de 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1848,6 +1848,7 @@ android.os.SharedMemory
android.os.ShellCallback
android.os.StatFs
android.os.StrictMode
+android.os.StrictMode$$Lambda$0
android.os.StrictMode$1
android.os.StrictMode$2
android.os.StrictMode$3
@@ -1872,6 +1873,7 @@ android.os.StrictMode$ThreadPolicy$Builder
android.os.StrictMode$ThreadSpanState
android.os.StrictMode$ViolationInfo
android.os.StrictMode$ViolationInfo$1
+android.os.StrictMode$ViolationLogger
android.os.StrictMode$VmPolicy
android.os.StrictMode$VmPolicy$Builder
android.os.SystemClock
@@ -2784,7 +2786,6 @@ com.android.internal.app.IVoiceInteractionManagerService$Stub
com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.NightDisplayController
-com.android.internal.app.NightDisplayController$1
com.android.internal.appwidget.IAppWidgetService
com.android.internal.appwidget.IAppWidgetService$Stub
com.android.internal.appwidget.IAppWidgetService$Stub$Proxy
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index bf9bd79e63ef..a3b3a9f21954 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -175,6 +175,9 @@ public abstract class AbstractAccountAuthenticator {
}
if (result != null) {
response.onResult(result);
+ } else {
+ response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+ "null bundle returned");
}
} catch (Exception e) {
handleException(response, "addAccount", accountType, e);
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index dd6ad55fba6d..bd9c9fa30536 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -2321,6 +2321,10 @@ public class AccountManager {
private class Response extends IAccountManagerResponse.Stub {
@Override
public void onResult(Bundle bundle) {
+ if (bundle == null) {
+ onError(ERROR_CODE_INVALID_RESPONSE, "null bundle returned");
+ return;
+ }
Intent intent = bundle.getParcelable(KEY_INTENT);
if (intent != null && mActivity != null) {
// since the user provided an Activity we will silently start intents
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a8665037f8d3..78d05f5123c8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -770,21 +770,6 @@ public class ActivityManager {
}
/**
- * Returns true if animation specs should be constructed for app transition that moves
- * the task to the specified stack.
- * @hide
- */
- public static boolean useAnimationSpecForAppTransition(int stackId) {
- // TODO: INVALID_STACK_ID is also animated because we don't persist stack id's across
- // reboots.
- return stackId == FREEFORM_WORKSPACE_STACK_ID
- || stackId == FULLSCREEN_WORKSPACE_STACK_ID
- || stackId == ASSISTANT_STACK_ID
- || stackId == DOCKED_STACK_ID
- || stackId == INVALID_STACK_ID;
- }
-
- /**
* Returns true if activities from stasks in the given {@param stackId} are allowed to
* enter picture-in-picture.
* @hide
@@ -885,6 +870,18 @@ public class ActivityManager {
return windowingMode;
}
+ /** Returns the stack id for the input windowing mode.
+ * @hide */
+ // TODO: To be removed once we are not using stack id for stuff...
+ public static int getStackIdForWindowingMode(int windowingMode) {
+ switch (windowingMode) {
+ case WINDOWING_MODE_PINNED: return PINNED_STACK_ID;
+ case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID;
+ default: return INVALID_STACK_ID;
+ }
+ }
+
/** Returns the activity type that should be used for this input stack id.
* @hide */
// TODO: To be removed once we are not using stack id for stuff...
@@ -905,6 +902,18 @@ public class ActivityManager {
}
return activityType;
}
+
+ /** Returns the stack id for the input activity type.
+ * @hide */
+ // TODO: To be removed once we are not using stack id for stuff...
+ public static int getStackIdForActivityType(int activityType) {
+ switch (activityType) {
+ case ACTIVITY_TYPE_HOME: return HOME_STACK_ID;
+ case ACTIVITY_TYPE_RECENTS: return RECENTS_STACK_ID;
+ case ACTIVITY_TYPE_ASSISTANT: return ASSISTANT_STACK_ID;
+ default: return INVALID_STACK_ID;
+ }
+ }
}
/**
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 0bffc9e6cee5..a68c3a5c29a6 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -18,6 +18,8 @@ package android.app;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.Nullable;
@@ -164,10 +166,16 @@ public class ActivityOptions {
private static final String KEY_LAUNCH_DISPLAY_ID = "android.activity.launchDisplayId";
/**
- * The stack id the activity should be launched into.
+ * The windowing mode the activity should be launched into.
* @hide
*/
- private static final String KEY_LAUNCH_STACK_ID = "android.activity.launchStackId";
+ private static final String KEY_LAUNCH_WINDOWING_MODE = "android.activity.windowingMode";
+
+ /**
+ * The activity type the activity should be launched as.
+ * @hide
+ */
+ private static final String KEY_LAUNCH_ACTIVITY_TYPE = "android.activity.activityType";
/**
* The task id the activity should be launched into.
@@ -272,7 +280,10 @@ public class ActivityOptions {
private int mExitCoordinatorIndex;
private PendingIntent mUsageTimeReport;
private int mLaunchDisplayId = INVALID_DISPLAY;
- private int mLaunchStackId = INVALID_STACK_ID;
+ @WindowConfiguration.WindowingMode
+ private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
+ @WindowConfiguration.ActivityType
+ private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
private int mLaunchTaskId = -1;
private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
private boolean mDisallowEnterPictureInPictureWhileLaunching;
@@ -860,7 +871,8 @@ public class ActivityOptions {
break;
}
mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
- mLaunchStackId = opts.getInt(KEY_LAUNCH_STACK_ID, INVALID_STACK_ID);
+ mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
+ mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
@@ -1070,14 +1082,34 @@ public class ActivityOptions {
}
/** @hide */
- public int getLaunchStackId() {
- return mLaunchStackId;
+ public int getLaunchWindowingMode() {
+ return mLaunchWindowingMode;
+ }
+
+ /**
+ * Sets the windowing mode the activity should launch into. If the input windowing mode is
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} and the device
+ * isn't currently in split-screen windowing mode, then the activity will be launched in
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_FULLSCREEN} windowing mode. For clarity
+ * on this you can use
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY}
+ *
+ * @hide
+ */
+ @TestApi
+ public void setLaunchWindowingMode(int windowingMode) {
+ mLaunchWindowingMode = windowingMode;
+ }
+
+ /** @hide */
+ public int getLaunchActivityType() {
+ return mLaunchActivityType;
}
/** @hide */
@TestApi
- public void setLaunchStackId(int launchStackId) {
- mLaunchStackId = launchStackId;
+ public void setLaunchActivityType(int activityType) {
+ mLaunchActivityType = activityType;
}
/**
@@ -1291,7 +1323,8 @@ public class ActivityOptions {
break;
}
b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
- b.putInt(KEY_LAUNCH_STACK_ID, mLaunchStackId);
+ b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
+ b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 0ceb28841e40..eccb264796f8 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -307,7 +307,15 @@ interface IActivityManager {
boolean shouldUpRecreateTask(in IBinder token, in String destAffinity);
boolean navigateUpTo(in IBinder token, in Intent target, int resultCode,
in Intent resultData);
- void setLockScreenShown(boolean showing);
+ /**
+ * Informs ActivityManagerService that the keyguard is showing.
+ *
+ * @param showing True if the keyguard is showing, false otherwise.
+ * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
+ * is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
+ * showing is true.
+ */
+ void setLockScreenShown(boolean showing, int secondaryDisplayShowing);
boolean finishActivityAffinity(in IBinder token);
// This is not public because you need to be very careful in how you
// manage your activity to make sure it is always the uid you expect.
@@ -545,11 +553,6 @@ interface IActivityManager {
*/
void resizePinnedStack(in Rect pinnedBounds, in Rect tempPinnedTaskBounds);
boolean isVrModePackageEnabled(in ComponentName packageName);
- /**
- * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the
- * fullscreen stack into the docked stack.
- */
- void swapDockedAndFullscreenStack();
void notifyLockedProfile(int userId);
void startConfirmDeviceCredentialIntent(in Intent intent, in Bundle options);
void sendIdleJobTrigger();
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 363e20a76a1f..578623892a9d 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -62,7 +62,10 @@ public class VrManager {
* @param callback The callback to register.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.RESTRICTED_VR_ACCESS,
+ android.Manifest.permission.ACCESS_VR_STATE
+ })
public void registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler) {
if (callback == null || mCallbackMap.containsKey(callback)) {
return;
@@ -88,7 +91,10 @@ public class VrManager {
* @param callback The callback to deregister.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.RESTRICTED_VR_ACCESS,
+ android.Manifest.permission.ACCESS_VR_STATE
+ })
public void unregisterVrStateCallback(VrStateCallback callback) {
CallbackEntry entry = mCallbackMap.remove(callback);
if (entry != null) {
@@ -110,7 +116,10 @@ public class VrManager {
* Returns the current VrMode state.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.RESTRICTED_VR_ACCESS,
+ android.Manifest.permission.ACCESS_VR_STATE
+ })
public boolean getVrModeEnabled() {
try {
return mService.getVrModeState();
@@ -124,7 +133,10 @@ public class VrManager {
* Returns the current VrMode state.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.RESTRICTED_VR_ACCESS,
+ android.Manifest.permission.ACCESS_VR_STATE
+ })
public boolean getPersistentVrModeEnabled() {
try {
return mService.getPersistentVrModeEnabled();
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 07eb5de15d9f..0cb38046826f 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -63,8 +63,21 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/**
* The containers adjacent to the {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} container in
* split-screen mode.
+ * NOTE: Containers launched with the windowing mode with APIs like
+ * {@link ActivityOptions#setLaunchWindowingMode(int)} will be launched in
+ * {@link #WINDOWING_MODE_FULLSCREEN} if the display isn't currently in split-screen windowing
+ * mode
+ * @see #WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
*/
public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4;
+ /**
+ * Alias for {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} that makes it clear that the usage
+ * points for APIs like {@link ActivityOptions#setLaunchWindowingMode(int)} that the container
+ * will launch into fullscreen or split-screen secondary depending on if the device is currently
+ * in fullscreen mode or split-screen mode.
+ */
+ public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY =
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
/** Can be freely resized within its parent container. */
public static final int WINDOWING_MODE_FREEFORM = 5;
@@ -75,6 +88,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
WINDOWING_MODE_PINNED,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY,
WINDOWING_MODE_FREEFORM,
})
public @interface WindowingMode {}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2d8249acb5bf..03e4dfe829de 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2991,6 +2991,7 @@ public abstract class Context {
//@hide: CONTEXTHUB_SERVICE,
SYSTEM_HEALTH_SERVICE,
//@hide: INCIDENT_SERVICE,
+ //@hide: STATS_COMPANION_SERVICE,
COMPANION_DEVICE_SERVICE
})
@Retention(RetentionPolicy.SOURCE)
@@ -4020,6 +4021,12 @@ public abstract class Context {
public static final String INCIDENT_SERVICE = "incident";
/**
+ * Service to assist statsd in obtaining general stats.
+ * @hide
+ */
+ public static final String STATS_COMPANION_SERVICE = "statscompanion";
+
+ /**
* Use with {@link #getSystemService} to retrieve a {@link
* android.content.om.OverlayManager} for managing overlay packages.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 08acfb651b18..c238ffbbaf4d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -10071,6 +10071,27 @@ public class Intent implements Parcelable, Cloneable {
return false;
}
+ /**
+ * Convert the dock state to a human readable format.
+ * @hide
+ */
+ public static String dockStateToString(int dock) {
+ switch (dock) {
+ case EXTRA_DOCK_STATE_HE_DESK:
+ return "EXTRA_DOCK_STATE_HE_DESK";
+ case EXTRA_DOCK_STATE_LE_DESK:
+ return "EXTRA_DOCK_STATE_LE_DESK";
+ case EXTRA_DOCK_STATE_CAR:
+ return "EXTRA_DOCK_STATE_CAR";
+ case EXTRA_DOCK_STATE_DESK:
+ return "EXTRA_DOCK_STATE_DESK";
+ case EXTRA_DOCK_STATE_UNDOCKED:
+ return "EXTRA_DOCK_STATE_UNDOCKED";
+ default:
+ return Integer.toString(dock);
+ }
+ }
+
private static ClipData.Item makeClipItem(ArrayList<Uri> streams, ArrayList<CharSequence> texts,
ArrayList<String> htmlTexts, int which) {
Uri uri = streams != null ? streams.get(which) : null;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 48587b3630d9..486ff43a6467 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -34,8 +34,7 @@ import java.lang.annotation.RetentionPolicy;
* from the AndroidManifest.xml's &lt;activity&gt; and
* &lt;receiver&gt; tags.
*/
-public class ActivityInfo extends ComponentInfo
- implements Parcelable {
+public class ActivityInfo extends ComponentInfo implements Parcelable {
// NOTE: When adding new data members be sure to update the copy-constructor, Parcel
// constructor, and writeToParcel.
@@ -1211,6 +1210,51 @@ public class ActivityInfo extends ComponentInfo
return isFloating || isTranslucent || isSwipeToDismiss;
}
+ /**
+ * Convert the screen orientation constant to a human readable format.
+ * @hide
+ */
+ public static String screenOrientationToString(int orientation) {
+ switch(orientation) {
+ case SCREEN_ORIENTATION_UNSET:
+ return "SCREEN_ORIENTATION_UNSET";
+ case SCREEN_ORIENTATION_UNSPECIFIED:
+ return "SCREEN_ORIENTATION_UNSPECIFIED";
+ case SCREEN_ORIENTATION_LANDSCAPE:
+ return "SCREEN_ORIENTATION_LANDSCAPE";
+ case SCREEN_ORIENTATION_PORTRAIT:
+ return "SCREEN_ORIENTATION_PORTRAIT";
+ case SCREEN_ORIENTATION_USER:
+ return "SCREEN_ORIENTATION_USER";
+ case SCREEN_ORIENTATION_BEHIND:
+ return "SCREEN_ORIENTATION_BEHIND";
+ case SCREEN_ORIENTATION_SENSOR:
+ return "SCREEN_ORIENTATION_SENSOR";
+ case SCREEN_ORIENTATION_NOSENSOR:
+ return "SCREEN_ORIENTATION_NOSENSOR";
+ case SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+ return "SCREEN_ORIENTATION_SENSOR_LANDSCAPE";
+ case SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+ return "SCREEN_ORIENTATION_SENSOR_PORTRAIT";
+ case SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+ return "SCREEN_ORIENTATION_REVERSE_LANDSCAPE";
+ case SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+ return "SCREEN_ORIENTATION_REVERSE_PORTRAIT";
+ case SCREEN_ORIENTATION_FULL_SENSOR:
+ return "SCREEN_ORIENTATION_FULL_SENSOR";
+ case SCREEN_ORIENTATION_USER_LANDSCAPE:
+ return "SCREEN_ORIENTATION_USER_LANDSCAPE";
+ case SCREEN_ORIENTATION_USER_PORTRAIT:
+ return "SCREEN_ORIENTATION_USER_PORTRAIT";
+ case SCREEN_ORIENTATION_FULL_USER:
+ return "SCREEN_ORIENTATION_FULL_USER";
+ case SCREEN_ORIENTATION_LOCKED:
+ return "SCREEN_ORIENTATION_LOCKED";
+ default:
+ return Integer.toString(orientation);
+ }
+ }
+
public static final Parcelable.Creator<ActivityInfo> CREATOR
= new Parcelable.Creator<ActivityInfo>() {
public ActivityInfo createFromParcel(Parcel source) {
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 1310e30300e2..dfd3bbf04d35 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1089,6 +1089,33 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
/**
+ * Convert the UI mode to a human readable format.
+ * @hide
+ */
+ public static String uiModeToString(int uiMode) {
+ switch (uiMode) {
+ case UI_MODE_TYPE_UNDEFINED:
+ return "UI_MODE_TYPE_UNDEFINED";
+ case UI_MODE_TYPE_NORMAL:
+ return "UI_MODE_TYPE_NORMAL";
+ case UI_MODE_TYPE_DESK:
+ return "UI_MODE_TYPE_DESK";
+ case UI_MODE_TYPE_CAR:
+ return "UI_MODE_TYPE_CAR";
+ case UI_MODE_TYPE_TELEVISION:
+ return "UI_MODE_TYPE_TELEVISION";
+ case UI_MODE_TYPE_APPLIANCE:
+ return "UI_MODE_TYPE_APPLIANCE";
+ case UI_MODE_TYPE_WATCH:
+ return "UI_MODE_TYPE_WATCH";
+ case UI_MODE_TYPE_VR_HEADSET:
+ return "UI_MODE_TYPE_VR_HEADSET";
+ default:
+ return Integer.toString(uiMode);
+ }
+ }
+
+ /**
* Set this object to the system defaults.
*/
public void setToDefaults() {
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
index ac6d83f622b2..26238304d8e9 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.java
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -287,8 +287,10 @@ public class NanoAppInstanceInfo {
mPublisher = in.readString();
mName = in.readString();
+ mHandle = in.readInt();
mAppId = in.readLong();
mAppVersion = in.readInt();
+ mContexthubId = in.readInt();
mNeededReadMemBytes = in.readInt();
mNeededWriteMemBytes = in.readInt();
mNeededExecMemBytes = in.readInt();
@@ -309,6 +311,8 @@ public class NanoAppInstanceInfo {
public void writeToParcel(Parcel out, int flags) {
out.writeString(mPublisher);
out.writeString(mName);
+
+ out.writeInt(mHandle);
out.writeLong(mAppId);
out.writeInt(mAppVersion);
out.writeInt(mContexthubId);
diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java
index d520b9745918..97e83f969c38 100644
--- a/core/java/android/net/metrics/WakeupStats.java
+++ b/core/java/android/net/metrics/WakeupStats.java
@@ -35,7 +35,7 @@ public class WakeupStats {
public long systemWakeups = 0;
public long nonApplicationWakeups = 0;
public long applicationWakeups = 0;
- public long unroutedWakeups = 0;
+ public long noUidWakeups = 0;
public long durationSec = 0;
public WakeupStats(String iface) {
@@ -58,7 +58,7 @@ public class WakeupStats {
systemWakeups++;
break;
case NO_UID:
- unroutedWakeups++;
+ noUidWakeups++;
break;
default:
if (ev.uid >= Process.FIRST_APPLICATION_UID) {
@@ -80,7 +80,7 @@ public class WakeupStats {
.append(", system: ").append(systemWakeups)
.append(", apps: ").append(applicationWakeups)
.append(", non-apps: ").append(nonApplicationWakeups)
- .append(", unrouted: ").append(unroutedWakeups)
+ .append(", no uid: ").append(noUidWakeups)
.append(", ").append(durationSec).append("s)")
.toString();
}
diff --git a/core/java/android/os/IStatsCompanionService.aidl b/core/java/android/os/IStatsCompanionService.aidl
new file mode 100644
index 000000000000..a29e375bcfbd
--- /dev/null
+++ b/core/java/android/os/IStatsCompanionService.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+/**
+ * Binder interface to communicate with the Java-based statistics service helper.
+ * {@hide}
+ */
+interface IStatsCompanionService {
+ /**
+ * Register an alarm for anomaly detection to fire at the given timestamp (ms since epoch).
+ * If anomaly alarm had already been registered, it will be replaced with the new timestamp.
+ * Uses AlarmManager.set API, so if the timestamp is in the past, alarm fires immediately, and
+ * alarm is inexact.
+ */
+ void setAnomalyAlarm(long timestampMs);
+ /** Cancel any anomaly detection alarm. */
+ void cancelAnomalyAlarm();
+
+ /**
+ * Register a repeating alarm for polling to fire at the given timestamp and every
+ * intervalMs thereafter (in ms since epoch).
+ * If polling alarm had already been registered, it will be replaced by new one.
+ * Uses AlarmManager.setRepeating API, so if the timestamp is in past, alarm fires immediately,
+ * and alarm is inexact.
+ */
+ void setPollingAlarms(long timestampMs, long intervalMs);
+ /** Cancel any repeating polling alarm. */
+ void cancelPollingAlarms();
+}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f02631c7fe61..2528439a5e1f 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -16,6 +16,7 @@
package android.os;
import android.animation.ValueAnimator;
+import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.ActivityThread;
@@ -322,16 +323,36 @@ public final class StrictMode {
/** {@hide} */
@TestApi
- public interface ViolationListener {
- public void onViolation(String message);
+ public interface ViolationLogger {
+
+ /** Called when penaltyLog is enabled and a violation needs logging. */
+ void log(ViolationInfo info);
}
- private static volatile ViolationListener sListener;
+ private static final ViolationLogger LOGCAT_LOGGER =
+ info -> {
+ String msg;
+ if (info.durationMillis != -1) {
+ msg = "StrictMode policy violation; ~duration=" + info.durationMillis + " ms:";
+ } else {
+ msg = "StrictMode policy violation:";
+ }
+ if (info.crashInfo != null) {
+ Log.d(TAG, msg + " " + info.crashInfo.stackTrace);
+ } else {
+ Log.d(TAG, msg + " missing stack trace!");
+ }
+ };
+
+ private static volatile ViolationLogger sLogger = LOGCAT_LOGGER;
/** {@hide} */
@TestApi
- public static void setViolationListener(ViolationListener listener) {
- sListener = listener;
+ public static void setViolationLogger(ViolationLogger listener) {
+ if (listener == null) {
+ listener = LOGCAT_LOGGER;
+ }
+ sLogger = listener;
}
/**
@@ -1512,28 +1533,16 @@ public final class StrictMode {
lastViolationTime = vtime;
}
} else {
- mLastViolationTime = new ArrayMap<Integer, Long>(1);
+ mLastViolationTime = new ArrayMap<>(1);
}
long now = SystemClock.uptimeMillis();
mLastViolationTime.put(crashFingerprint, now);
long timeSinceLastViolationMillis =
lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime);
- if ((info.policy & PENALTY_LOG) != 0 && sListener != null) {
- sListener.onViolation(info.crashInfo.stackTrace);
- }
if ((info.policy & PENALTY_LOG) != 0
&& timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
- if (info.durationMillis != -1) {
- Log.d(
- TAG,
- "StrictMode policy violation; ~duration="
- + info.durationMillis
- + " ms: "
- + info.crashInfo.stackTrace);
- } else {
- Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
- }
+ sLogger.log(info);
}
// The violationMaskSubset, passed to ActivityManager, is a
@@ -1925,11 +1934,11 @@ public final class StrictMode {
}
}
- if (penaltyLog && sListener != null) {
- sListener.onViolation(originStack.toString());
+ if (penaltyLog && sLogger != null) {
+ sLogger.log(info);
}
if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
- Log.e(TAG, message, originStack);
+ sLogger.log(info);
}
int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicy.mask);
@@ -2339,11 +2348,12 @@ public final class StrictMode {
*
* @hide
*/
- public static class ViolationInfo implements Parcelable {
+ @TestApi
+ public static final class ViolationInfo implements Parcelable {
public final String message;
/** Stack and other stuff info. */
- public final ApplicationErrorReport.CrashInfo crashInfo;
+ @Nullable public final ApplicationErrorReport.CrashInfo crashInfo;
/** The strict mode policy mask at the time of violation. */
public final int policy;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 40ced6ce4815..a5c55ba74a70 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6966,8 +6966,9 @@ public final class Settings {
public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
/**
- * Time in milliseconds (since epoch) when Night display was last activated. Use to decide
- * whether to apply the current activated state after a reboot or user change.
+ * A String representing the LocalDateTime when Night display was last activated. Use to
+ * decide whether to apply the current activated state after a reboot or user change. In
+ * legacy cases, this is represented by the time in milliseconds (since epoch).
* @hide
*/
public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME =
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 2c1f73468ca6..ddced6cdd83f 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -762,7 +762,7 @@ public class Surface implements Parcelable {
return "ROTATION_270";
}
default: {
- throw new IllegalArgumentException("Invalid rotation: " + rotation);
+ return Integer.toString(rotation);
}
}
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 66506a18296b..4131fd1ae9ff 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -617,6 +617,38 @@ public interface WindowManagerPolicy {
* @param listener callback to call when display can be turned off
*/
void screenTurningOff(ScreenOffListener listener);
+
+ /**
+ * Convert the lid state to a human readable format.
+ */
+ static String lidStateToString(int lid) {
+ switch (lid) {
+ case LID_ABSENT:
+ return "LID_ABSENT";
+ case LID_CLOSED:
+ return "LID_CLOSED";
+ case LID_OPEN:
+ return "LID_OPEN";
+ default:
+ return Integer.toString(lid);
+ }
+ }
+
+ /**
+ * Convert the camera lens state to a human readable format.
+ */
+ static String cameraLensStateToString(int lens) {
+ switch (lens) {
+ case CAMERA_LENS_COVER_ABSENT:
+ return "CAMERA_LENS_COVER_ABSENT";
+ case CAMERA_LENS_UNCOVERED:
+ return "CAMERA_LENS_UNCOVERED";
+ case CAMERA_LENS_COVERED:
+ return "CAMERA_LENS_COVERED";
+ default:
+ return Integer.toString(lens);
+ }
+ }
}
public interface PointerEventListener {
@@ -1750,4 +1782,34 @@ public interface WindowManagerPolicy {
* @return true if ready; false otherwise.
*/
boolean canDismissBootAnimation();
+
+ /**
+ * Convert the user rotation mode to a human readable format.
+ */
+ static String userRotationModeToString(int mode) {
+ switch(mode) {
+ case USER_ROTATION_FREE:
+ return "USER_ROTATION_FREE";
+ case USER_ROTATION_LOCKED:
+ return "USER_ROTATION_LOCKED";
+ default:
+ return Integer.toString(mode);
+ }
+ }
+
+ /**
+ * Convert the off reason to a human readable format.
+ */
+ static String offReasonToString(int why) {
+ switch (why) {
+ case OFF_BECAUSE_OF_ADMIN:
+ return "OFF_BECAUSE_OF_ADMIN";
+ case OFF_BECAUSE_OF_USER:
+ return "OFF_BECAUSE_OF_USER";
+ case OFF_BECAUSE_OF_TIMEOUT:
+ return "OFF_BECAUSE_OF_TIMEOUT";
+ default:
+ return Integer.toString(why);
+ }
+ }
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 61cbce976844..f888ba298339 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -37,14 +37,13 @@ import android.service.autofill.AutofillService;
import android.service.autofill.FillEventHistory;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.DebugUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -202,9 +201,12 @@ public final class AutofillManager {
* Initial state of the autofill context, set when there is no session (i.e., when
* {@link #mSessionId} is {@link #NO_SESSION}).
*
+ * <p>In this state, app callbacks (such as {@link #notifyViewEntered(View)}) are notified to
+ * the server.
+ *
* @hide
*/
- public static final int STATE_UNKNOWN = 1;
+ public static final int STATE_UNKNOWN = 0;
/**
* State where the autofill context hasn't been {@link #commit() finished} nor
@@ -212,7 +214,18 @@ public final class AutofillManager {
*
* @hide
*/
- public static final int STATE_ACTIVE = 2;
+ public static final int STATE_ACTIVE = 1;
+
+ /**
+ * State where the autofill context was finished by the server because the autofill
+ * service could not autofill the page.
+ *
+ * <p>In this state, most apps callback (such as {@link #notifyViewEntered(View)}) are ignored,
+ * exception {@link #requestAutofill(View)} (and {@link #requestAutofill(View, int, Rect)}).
+ *
+ * @hide
+ */
+ public static final int STATE_FINISHED = 2;
/**
* State where the autofill context has been {@link #commit() finished} but the server still has
@@ -220,7 +233,7 @@ public final class AutofillManager {
*
* @hide
*/
- public static final int STATE_SHOWING_SAVE_UI = 4;
+ public static final int STATE_SHOWING_SAVE_UI = 3;
/**
* Makes an authentication id from a request id and a dataset id.
@@ -559,6 +572,14 @@ public final class AutofillManager {
}
AutofillCallback callback = null;
synchronized (mLock) {
+ if (isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
+ if (sVerbose) {
+ Log.v(TAG, "notifyViewEntered(flags=" + flags + ", view=" + view
+ + "): ignored on state " + getStateAsStringLocked());
+ }
+ return;
+ }
+
ensureServiceClientAddedIfNeededLocked();
if (!mEnabled) {
@@ -682,6 +703,14 @@ public final class AutofillManager {
}
AutofillCallback callback = null;
synchronized (mLock) {
+ if (isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
+ if (sVerbose) {
+ Log.v(TAG, "notifyViewEntered(flags=" + flags + ", view=" + view
+ + ", virtualId=" + virtualId
+ + "): ignored on state " + getStateAsStringLocked());
+ }
+ return;
+ }
ensureServiceClientAddedIfNeededLocked();
if (!mEnabled) {
@@ -765,6 +794,10 @@ public final class AutofillManager {
}
if (!mEnabled || !isActiveLocked()) {
+ if (sVerbose && mEnabled) {
+ Log.v(TAG, "notifyValueChanged(" + view + "): ignoring on state "
+ + getStateAsStringLocked());
+ }
return;
}
@@ -950,10 +983,13 @@ public final class AutofillManager {
@NonNull AutofillValue value, int flags) {
if (sVerbose) {
Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value
- + ", flags=" + flags + ", state=" + mState);
+ + ", flags=" + flags + ", state=" + getStateAsStringLocked());
}
- if (mState != STATE_UNKNOWN) {
- if (sDebug) Log.d(TAG, "not starting session for " + id + " on state " + mState);
+ if (mState != STATE_UNKNOWN && (flags & FLAG_MANUAL_REQUEST) == 0) {
+ if (sVerbose) {
+ Log.v(TAG, "not automatically starting session for " + id
+ + " on state " + getStateAsStringLocked());
+ }
return;
}
try {
@@ -973,7 +1009,7 @@ public final class AutofillManager {
}
private void finishSessionLocked() {
- if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + mState);
+ if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + getStateAsStringLocked());
if (!isActiveLocked()) return;
@@ -987,7 +1023,7 @@ public final class AutofillManager {
}
private void cancelSessionLocked() {
- if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + mState);
+ if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + getStateAsStringLocked());
if (!isActiveLocked()) return;
@@ -1245,10 +1281,10 @@ public final class AutofillManager {
}
}
- final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
- log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
- log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED,
- numApplied);
+ final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_DATASET_APPLIED)
+ .setPackageName(mContext.getPackageName())
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied);
mMetricsLogger.write(log);
}
}
@@ -1306,6 +1342,14 @@ public final class AutofillManager {
}
}
+ private void setSessionFinished() {
+ if (sVerbose) Log.v(TAG, "setSessionFinished()");
+ synchronized (mLock) {
+ resetSessionLocked();
+ mState = STATE_FINISHED;
+ }
+ }
+
private void requestHideFillUi(AutofillId id) {
final View anchor = findView(id);
if (sVerbose) Log.v(TAG, "requestHideFillUi(" + id + "): anchor = " + anchor);
@@ -1341,7 +1385,11 @@ public final class AutofillManager {
}
}
- private void notifyNoFillUi(int sessionId, AutofillId id) {
+ private void notifyNoFillUi(int sessionId, AutofillId id, boolean sessionFinished) {
+ if (sVerbose) {
+ Log.v(TAG, "notifyNoFillUi(): sessionId=" + sessionId + ", autofillId=" + id
+ + ", finished=" + sessionFinished);
+ }
final View anchor = findView(id);
if (anchor == null) {
return;
@@ -1361,7 +1409,11 @@ public final class AutofillManager {
} else {
callback.onAutofillEvent(anchor, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
}
+ }
+ if (sessionFinished) {
+ // Callback call was "hijacked" to also update the session state.
+ setSessionFinished();
}
}
@@ -1434,8 +1486,7 @@ public final class AutofillManager {
pw.print(outerPrefix); pw.println("AutofillManager:");
final String pfx = outerPrefix + " ";
pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId);
- pw.print(pfx); pw.print("state: "); pw.println(
- DebugUtils.flagsToString(AutofillManager.class, "STATE_", mState));
+ pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked());
pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);
pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);
pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null);
@@ -1452,10 +1503,29 @@ public final class AutofillManager {
pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds);
}
+ private String getStateAsStringLocked() {
+ switch (mState) {
+ case STATE_UNKNOWN:
+ return "STATE_UNKNOWN";
+ case STATE_ACTIVE:
+ return "STATE_ACTIVE";
+ case STATE_FINISHED:
+ return "STATE_FINISHED";
+ case STATE_SHOWING_SAVE_UI:
+ return "STATE_SHOWING_SAVE_UI";
+ default:
+ return "INVALID:" + mState;
+ }
+ }
+
private boolean isActiveLocked() {
return mState == STATE_ACTIVE;
}
+ private boolean isFinishedLocked() {
+ return mState == STATE_FINISHED;
+ }
+
private void post(Runnable runnable) {
final AutofillClient client = getClientLocked();
if (client == null) {
@@ -1787,10 +1857,10 @@ public final class AutofillManager {
}
@Override
- public void notifyNoFillUi(int sessionId, AutofillId id) {
+ public void notifyNoFillUi(int sessionId, AutofillId id, boolean sessionFinished) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
- afm.post(() -> afm.notifyNoFillUi(sessionId, id));
+ afm.post(() -> afm.notifyNoFillUi(sessionId, id, sessionFinished));
}
}
@@ -1823,7 +1893,15 @@ public final class AutofillManager {
public void setSaveUiState(int sessionId, boolean shown) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
- afm.post(() ->afm.setSaveUiState(sessionId, shown));
+ afm.post(() -> afm.setSaveUiState(sessionId, shown));
+ }
+ }
+
+ @Override
+ public void setSessionFinished() {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.post(() -> afm.setSessionFinished());
}
}
}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 0eae85860383..db6855a4dbf4 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -67,9 +67,9 @@ oneway interface IAutoFillManagerClient {
void requestHideFillUi(int sessionId, in AutofillId id);
/**
- * Notifies no fill UI will be shown.
+ * Notifies no fill UI will be shown, and also mark the state as finished if necessary.
*/
- void notifyNoFillUi(int sessionId, in AutofillId id);
+ void notifyNoFillUi(int sessionId, in AutofillId id, boolean sessionFinished);
/**
* Starts the provided intent sender.
@@ -80,4 +80,10 @@ oneway interface IAutoFillManagerClient {
* Sets the state of the Autofill Save UI for a given session.
*/
void setSaveUiState(int sessionId, boolean shown);
+
+ /**
+ * Marks the state of the session as finished (because the AutofillService returned a null
+ * FillResponse).
+ */
+ void setSessionFinished();
}
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 7c4154f5c648..994512f7c897 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -463,7 +463,7 @@ public final class WebViewFactory {
*/
public static int onWebViewProviderChanged(PackageInfo packageInfo) {
String[] nativeLibs = null;
- String originalSourceDir = packageInfo.applicationInfo.sourceDir;
+ ApplicationInfo originalAppInfo = new ApplicationInfo(packageInfo.applicationInfo);
try {
fixupStubApplicationInfo(packageInfo.applicationInfo,
AppGlobals.getInitialApplication().getPackageManager());
@@ -474,7 +474,7 @@ public final class WebViewFactory {
Log.e(LOGTAG, "error preparing webview native library", t);
}
- WebViewZygote.onWebViewProviderChanged(packageInfo, originalSourceDir);
+ WebViewZygote.onWebViewProviderChanged(packageInfo, originalAppInfo);
return prepareWebViewInSystemServer(nativeLibs);
}
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index 6e65c7a11d2f..db60ad8d1c05 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -17,6 +17,7 @@
package android.webkit;
import android.app.LoadedApk;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.SystemService;
@@ -67,11 +68,11 @@ public class WebViewZygote {
private static PackageInfo sPackage;
/**
- * Cache key for the selected WebView package's classloader. This is set from
+ * Original ApplicationInfo for the selected WebView package before stub fixup. This is set from
* #onWebViewProviderChanged().
*/
@GuardedBy("sLock")
- private static String sPackageCacheKey;
+ private static ApplicationInfo sPackageOriginalAppInfo;
/**
* Flag for whether multi-process WebView is enabled. If this is {@code false}, the zygote
@@ -125,10 +126,11 @@ public class WebViewZygote {
}
}
- public static void onWebViewProviderChanged(PackageInfo packageInfo, String cacheKey) {
+ public static void onWebViewProviderChanged(PackageInfo packageInfo,
+ ApplicationInfo originalAppInfo) {
synchronized (sLock) {
sPackage = packageInfo;
- sPackageCacheKey = cacheKey;
+ sPackageOriginalAppInfo = originalAppInfo;
// If multi-process is not enabled, then do not start the zygote service.
if (!sMultiprocessEnabled) {
@@ -217,10 +219,17 @@ public class WebViewZygote {
final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
TextUtils.join(File.pathSeparator, zipPaths);
+ // In the case where the ApplicationInfo has been modified by the stub WebView,
+ // we need to use the original ApplicationInfo to determine what the original classpath
+ // would have been to use as a cache key.
+ LoadedApk.makePaths(null, false, sPackageOriginalAppInfo, zipPaths, null);
+ final String cacheKey = (zipPaths.size() == 1) ? zipPaths.get(0) :
+ TextUtils.join(File.pathSeparator, zipPaths);
+
ZygoteProcess.waitForConnectionToZygote(WEBVIEW_ZYGOTE_SOCKET);
Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
- sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey,
+ sZygote.preloadPackageForAbi(zip, librarySearchPath, cacheKey,
Build.SUPPORTED_ABIS[0]);
} catch (Exception e) {
Log.e(LOGTAG, "Error connecting to " + serviceName, e);
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index bc85fadb5ad9..7903d6fdc614 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -16,9 +16,10 @@
package android.widget;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.annotation.ColorInt;
import android.annotation.DimenRes;
-import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
@@ -324,11 +325,11 @@ public class RemoteViews implements Parcelable, Filter {
public boolean onClickHandler(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
- return onClickHandler(view, pendingIntent, fillInIntent, StackId.INVALID_STACK_ID);
+ return onClickHandler(view, pendingIntent, fillInIntent, WINDOWING_MODE_UNDEFINED);
}
public boolean onClickHandler(View view, PendingIntent pendingIntent,
- Intent fillInIntent, int launchStackId) {
+ Intent fillInIntent, int windowingMode) {
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
Context context = view.getContext();
@@ -339,8 +340,8 @@ public class RemoteViews implements Parcelable, Filter {
opts = ActivityOptions.makeBasic();
}
- if (launchStackId != StackId.INVALID_STACK_ID) {
- opts.setLaunchStackId(launchStackId);
+ if (windowingMode != WINDOWING_MODE_UNDEFINED) {
+ opts.setLaunchWindowingMode(windowingMode);
}
context.startIntentSender(
pendingIntent.getIntentSender(), fillInIntent,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index efcc3a2f7a2b..2de552777756 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5549,7 +5549,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public final void setHint(CharSequence hint) {
setHintInternal(hint);
- if (isInputMethodTarget()) {
+ if (mEditor != null && isInputMethodTarget()) {
mEditor.reportExtractedText();
}
}
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
index 860c5c4c3d3b..7a1383c7a01c 100644
--- a/core/java/com/android/internal/app/NightDisplayController.java
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -32,8 +32,12 @@ import com.android.internal.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Calendar;
-import java.util.Locale;
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeParseException;
/**
* Controller for managing Night display settings.
@@ -116,8 +120,9 @@ public final class NightDisplayController {
*/
public boolean setActivated(boolean activated) {
if (isActivated() != activated) {
- Secure.putLongForUser(mContext.getContentResolver(),
- Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
+ Secure.putStringForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
+ LocalDateTime.now().toString(),
mUserId);
}
return Secure.putIntForUser(mContext.getContentResolver(),
@@ -128,17 +133,22 @@ public final class NightDisplayController {
* Returns the time when Night display's activation state last changed, or {@code null} if it
* has never been changed.
*/
- public Calendar getLastActivatedTime() {
+ public LocalDateTime getLastActivatedTime() {
final ContentResolver cr = mContext.getContentResolver();
- final long lastActivatedTimeMillis = Secure.getLongForUser(
- cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mUserId);
- if (lastActivatedTimeMillis < 0) {
- return null;
+ final String lastActivatedTime = Secure.getStringForUser(
+ cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, mUserId);
+ if (lastActivatedTime != null) {
+ try {
+ return LocalDateTime.parse(lastActivatedTime);
+ } catch (DateTimeParseException ignored) {}
+ // Uses the old epoch time.
+ try {
+ return LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(Long.parseLong(lastActivatedTime)),
+ ZoneId.systemDefault());
+ } catch (DateTimeException|NumberFormatException ignored) {}
}
-
- final Calendar lastActivatedTime = Calendar.getInstance();
- lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
- return lastActivatedTime;
+ return null;
}
/**
@@ -183,8 +193,10 @@ public final class NightDisplayController {
}
if (getAutoMode() != autoMode) {
- Secure.putLongForUser(mContext.getContentResolver(),
- Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1L, mUserId);
+ Secure.putStringForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
+ null,
+ mUserId);
}
return Secure.putIntForUser(mContext.getContentResolver(),
Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId);
@@ -206,7 +218,7 @@ public final class NightDisplayController {
R.integer.config_defaultNightDisplayCustomStartTime);
}
- return LocalTime.valueOf(startTimeValue);
+ return LocalTime.ofSecondOfDay(startTimeValue / 1000);
}
/**
@@ -221,7 +233,7 @@ public final class NightDisplayController {
throw new IllegalArgumentException("startTime cannot be null");
}
return Secure.putIntForUser(mContext.getContentResolver(),
- Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toMillis(), mUserId);
+ Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toSecondOfDay() * 1000, mUserId);
}
/**
@@ -240,7 +252,7 @@ public final class NightDisplayController {
R.integer.config_defaultNightDisplayCustomEndTime);
}
- return LocalTime.valueOf(endTimeValue);
+ return LocalTime.ofSecondOfDay(endTimeValue / 1000);
}
/**
@@ -255,7 +267,7 @@ public final class NightDisplayController {
throw new IllegalArgumentException("endTime cannot be null");
}
return Secure.putIntForUser(mContext.getContentResolver(),
- Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId);
+ Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toSecondOfDay() * 1000, mUserId);
}
/**
@@ -379,106 +391,6 @@ public final class NightDisplayController {
}
/**
- * A time without a time-zone or date.
- */
- public static class LocalTime {
-
- /**
- * The hour of the day from 0 - 23.
- */
- public final int hourOfDay;
- /**
- * The minute within the hour from 0 - 59.
- */
- public final int minute;
-
- public LocalTime(int hourOfDay, int minute) {
- if (hourOfDay < 0 || hourOfDay > 23) {
- throw new IllegalArgumentException("Invalid hourOfDay: " + hourOfDay);
- } else if (minute < 0 || minute > 59) {
- throw new IllegalArgumentException("Invalid minute: " + minute);
- }
-
- this.hourOfDay = hourOfDay;
- this.minute = minute;
- }
-
- /**
- * Returns the first date time corresponding to this local time that occurs before the
- * provided date time.
- *
- * @param time the date time to compare against
- * @return the prior date time corresponding to this local time
- */
- public Calendar getDateTimeBefore(Calendar time) {
- final Calendar c = Calendar.getInstance();
- c.set(Calendar.YEAR, time.get(Calendar.YEAR));
- c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));
-
- c.set(Calendar.HOUR_OF_DAY, hourOfDay);
- c.set(Calendar.MINUTE, minute);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
-
- // Check if the local time has past, if so return the same time tomorrow.
- if (c.after(time)) {
- c.add(Calendar.DATE, -1);
- }
-
- return c;
- }
-
- /**
- * Returns the first date time corresponding to this local time that occurs after the
- * provided date time.
- *
- * @param time the date time to compare against
- * @return the next date time corresponding to this local time
- */
- public Calendar getDateTimeAfter(Calendar time) {
- final Calendar c = Calendar.getInstance();
- c.set(Calendar.YEAR, time.get(Calendar.YEAR));
- c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));
-
- c.set(Calendar.HOUR_OF_DAY, hourOfDay);
- c.set(Calendar.MINUTE, minute);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
-
- // Check if the local time has past, if so return the same time tomorrow.
- if (c.before(time)) {
- c.add(Calendar.DATE, 1);
- }
-
- return c;
- }
-
- /**
- * Returns a local time corresponding the given number of milliseconds from midnight.
- *
- * @param millis the number of milliseconds from midnight
- * @return the corresponding local time
- */
- private static LocalTime valueOf(int millis) {
- final int hourOfDay = (millis / 3600000) % 24;
- final int minutes = (millis / 60000) % 60;
- return new LocalTime(hourOfDay, minutes);
- }
-
- /**
- * Returns the local time represented as milliseconds from midnight.
- */
- private int toMillis() {
- return hourOfDay * 3600000 + minute * 60000;
- }
-
- @Override
- public String toString() {
- return String.format(Locale.US, "%02d:%02d", hourOfDay, minute);
- }
- }
-
- /**
* Callback invoked whenever the Night display settings are changed.
*/
public interface Callback {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 5ee0918c336a..cbc63cf813cb 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -49,6 +49,11 @@ public final class Zygote {
/** Make the code Java debuggable by turning off some optimizations. */
public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8;
+ /** Turn off the verifier. */
+ public static final int DISABLE_VERIFIER = 1 << 9;
+ /** Only use oat files located in /system. Otherwise use dex/jar/apk . */
+ public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
+
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8122eb7de9b9..695fdac70280 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3074,6 +3074,12 @@
<permission android:name="android.permission.BATTERY_STATS"
android:protectionLevel="signature|privileged|development" />
+ <!--Allows an application to manage statscompanion.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.STATSCOMPANION"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to control the backup and restore process.
<p>Not for use by third-party applications.
@hide pending API council -->
@@ -3859,6 +3865,16 @@
</intent-filter>
</receiver>
+ <receiver android:name="com.android.server.stats.StatsCompanionService$AnomalyAlarmReceiver"
+ android:permission="android.permission.STATSCOMPANION"
+ android:exported="false">
+ </receiver>
+
+ <receiver android:name="com.android.server.stats.StatsCompanionService$PollingAlarmReceiver"
+ android:permission="android.permission.STATSCOMPANION"
+ android:exported="false">
+ </receiver>
+
<service android:name="android.hardware.location.GeofenceHardwareService"
android:permission="android.permission.LOCATION_HARDWARE"
android:exported="false" />
@@ -3910,6 +3926,9 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
+ <service android:name="com.android.server.timezone.TimeZoneUpdateIdler"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
</application>
</manifest>
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 92419c8c525b..5c5b985b26a2 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -46,13 +46,14 @@
<ImageView
android:id="@+id/autofill_save_icon"
- android:layout_width="wrap_content"
- android:layout_height="24sp"/>
+ android:scaleType="fitStart"
+ android:layout_width="24dp"
+ android:layout_height="24dp"/>
<TextView
android:id="@+id/autofill_save_title"
android:paddingLeft="8dp"
- android:layout_width="0dp"
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/autofill_save_title"
android:textSize="16sp"
diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index 50e29c2863c2..9d75c784fe41 100644
--- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -267,7 +267,7 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT
* @throws Exception
*/
@SmallTest
- public void testPhoneNumbersEqualInternationl() throws Exception {
+ public void testPhoneNumbersEqualInternational() throws Exception {
assertPhoneNumberEqual("1", "1");
assertPhoneNumberEqual("123123", "123123");
assertPhoneNumberNotEqual("123123", "923123");
@@ -288,6 +288,16 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT
// French trunk digit
assertPhoneNumberEqual("+33123456789", "0123456789");
+ // Hungarian two digit trunk (currently only works for loose comparison)
+ assertPhoneNumberEqual("+36 1 234 5678", "06 1234-5678", false);
+
+ // Mexican two digit trunk (currently only works for loose comparison)
+ assertPhoneNumberEqual("+52 55 1234 5678", "01 55 1234 5678", false);
+
+ // Mongolian two digit trunk (currently only works for loose comparison)
+ assertPhoneNumberEqual("+976 1 123 4567", "01 1 23 4567", false);
+ assertPhoneNumberEqual("+976 2 234 5678", "02 2 34 5678", false);
+
// Trunk digit for city codes in the Netherlands
assertPhoneNumberEqual("+31771234567", "0771234567");
@@ -317,9 +327,22 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT
assertPhoneNumberEqual("008001231234", "8001231234", false);
assertPhoneNumberNotEqual("008001231234", "8001231234", true);
- // Confirm that the bug found before does not re-appear in the strict compalation
- assertPhoneNumberEqual("080-1234-5678", "+819012345678", false);
- assertPhoneNumberNotEqual("080-1234-5678", "+819012345678", true);
+ // Confirm that the bug found before does not re-appear
+ assertPhoneNumberNotEqual("080-1234-5678", "+819012345678");
+
+ // Wrong prefix for Japan (currently only works for loose comparison)
+ assertPhoneNumberNotEqual("290-1234-5678", "+819012345678", false);
+ assertPhoneNumberNotEqual("+819012345678", "290-1234-5678", false);
+
+ // Wrong prefix for USA
+ assertPhoneNumberNotEqual("550-450-3605", "+14504503605");
+ assertPhoneNumberNotEqual("550-450-3605", "+15404503605");
+ assertPhoneNumberNotEqual("550-450-3605", "+15514503605");
+ assertPhoneNumberNotEqual("5504503605", "+14504503605");
+ assertPhoneNumberNotEqual("+14504503605", "550-450-3605");
+ assertPhoneNumberNotEqual("+15404503605", "550-450-3605");
+ assertPhoneNumberNotEqual("+15514503605", "550-450-3605");
+ assertPhoneNumberNotEqual("+14504503605", "5504503605");
}
@MediumTest
diff --git a/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java b/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java
index bcd90600b48a..75809c0fce4b 100644
--- a/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java
+++ b/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java
@@ -18,41 +18,70 @@ package android.database;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
+import android.os.SystemProperties;
import android.test.PerformanceTestCase;
+import android.util.ArrayMap;
import android.util.Log;
import junit.framework.TestCase;
import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
import java.util.Random;
/**
- * Database Performance Tests
- *
+ * Database Performance Tests.
+ *
+ * <p>Usage:
+ * <code>./frameworks/base/core/tests/coretests/src/android/database/run_newdb_perf_test.sh</code>
+ * <p>Test with WAL journaling enabled:
+ * <code>setprop debug.NewDatabasePerformanceTests.enable_wal 1</code>
*/
-
public class NewDatabasePerformanceTests {
private static final String TAG = "NewDatabasePerformanceTests";
+ private static final boolean DEBUG_ENABLE_WAL = SystemProperties
+ .getBoolean("debug.NewDatabasePerformanceTests.enable_wal", false);
+
private static final int DATASET_SIZE = 100; // Size of dataset to use for testing
private static final int FAST_OP_MULTIPLIER = 25;
private static final int FAST_OP_COUNT = FAST_OP_MULTIPLIER * DATASET_SIZE;
+ private static Long sInitialWriteBytes;
+
+ static {
+ sInitialWriteBytes = getIoStats().get("write_bytes");
+ if (DEBUG_ENABLE_WAL) {
+ Log.i(TAG, "Testing with WAL enabled");
+ }
+ }
+
public static class PerformanceBase extends TestCase
- implements PerformanceTestCase {
+ implements PerformanceTestCase {
protected static final int CURRENT_DATABASE_VERSION = 42;
protected SQLiteDatabase mDatabase;
protected File mDatabaseFile;
private long mSetupFinishedTime;
+ private Long mSetupWriteBytes;
public void setUp() {
long setupStarted = System.currentTimeMillis();
mDatabaseFile = new File("/sdcard", "perf_database_test.db");
if (mDatabaseFile.exists()) {
- mDatabaseFile.delete();
+ SQLiteDatabase.deleteDatabase(mDatabaseFile);
+ }
+ SQLiteDatabase.OpenParams.Builder params = new SQLiteDatabase.OpenParams.Builder();
+ params.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
+ if (DEBUG_ENABLE_WAL) {
+ params.addOpenFlags(SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING);
+ }
+ mDatabase = SQLiteDatabase.openDatabase(mDatabaseFile, params.build());
+ if (DEBUG_ENABLE_WAL) {
+ assertTrue("Cannot enable WAL", mDatabase.isWriteAheadLoggingEnabled());
}
- mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
- assertTrue(mDatabase != null);
mDatabase.setVersion(CURRENT_DATABASE_VERSION);
mDatabase.beginTransactionNonExclusive();
prepareForTest();
@@ -61,6 +90,7 @@ public class NewDatabasePerformanceTests {
mSetupFinishedTime = System.currentTimeMillis();
Log.i(TAG, "Setup for " + getClass().getSimpleName() + " took "
+ (mSetupFinishedTime - setupStarted) + " ms");
+ mSetupWriteBytes = getIoStats().get("write_bytes");
}
protected void prepareForTest() {
@@ -70,7 +100,14 @@ public class NewDatabasePerformanceTests {
long duration = System.currentTimeMillis() - mSetupFinishedTime;
Log.i(TAG, "Test " + getClass().getSimpleName() + " took " + duration + " ms");
mDatabase.close();
- mDatabaseFile.delete();
+ SQLiteDatabase.deleteDatabase(mDatabaseFile);
+ Long writeBytes = getIoStats().get("write_bytes");
+ if (writeBytes != null && sInitialWriteBytes != null) {
+ long testWriteBytes = writeBytes - mSetupWriteBytes;
+ long totalWriteBytes = (writeBytes - sInitialWriteBytes);
+ Log.i(TAG, "Test " + getClass().getSimpleName() + " write_bytes=" + testWriteBytes
+ + ". Since tests started - totalWriteBytes=" + totalWriteBytes);
+ }
}
public boolean isPerformanceOnly() {
@@ -897,4 +934,31 @@ public class NewDatabasePerformanceTests {
static final String[] TENS =
{"", "ten", "twenty", "thirty", "forty", "fifty", "sixty",
"seventy", "eighty", "ninety"};
+
+ static Map<String, Long> getIoStats() {
+ String ioStat = "/proc/self/io";
+ Map<String, Long> results = new ArrayMap<>();
+ try {
+ List<String> lines = Files.readAllLines(new File(ioStat).toPath());
+ for (String line : lines) {
+ line = line.trim();
+ String[] split = line.split(":");
+ if (split.length == 2) {
+ try {
+ String key = split[0].trim();
+ Long value = Long.valueOf(split[1].trim());
+ results.put(key, value);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Cannot parse number from " + line);
+ }
+ } else if (line.isEmpty()) {
+ Log.e(TAG, "Cannot parse line " + line);
+ }
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Can't read: " + ioStat, e);
+ }
+ return results;
+ }
+
}
diff --git a/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py b/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py
index 1faeceb78d8b..27b20c327c0b 100644
--- a/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py
+++ b/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py
@@ -25,7 +25,16 @@ def main():
all_lines = f.readlines()
timings = {}
running_sum = 0
+ # If WAL was enabled for the test
+ wal_enabled = False
+ # Number of bytes which test process caused to be sent to the storage layer.
+ # Reported as max value across all runs.
+ max_write_bytes = 0
for line in all_lines:
+ if "NewDatabasePerformanceTests: Testing with WAL enabled" in line:
+ wal_enabled = True
+ continue
+
regex = r"NewDatabasePerformanceTests: Test (\w+) took (\d+) ms"
matches = re.search(regex, line)
if matches:
@@ -35,16 +44,31 @@ def main():
timings[test_name] = []
timings[test_name].append(duration)
running_sum += duration
+ continue
+
if ("TestRunner: run finished:" in line) and (running_sum > 0):
- test_name = '*** TOTAL ALL TESTS (ms) ***'
+ test_name = ('*** TOTAL ALL TESTS [WAL] (ms) ***' if wal_enabled
+ else '*** TOTAL ALL TESTS (ms) ***')
if not test_name in timings:
timings[test_name] = []
timings[test_name].append(running_sum)
running_sum=0
+ continue
+
+ # Determine max from all reported totalWriteBytes
+ regex = r"Test .* totalWriteBytes=(\d+)"
+ matches = re.search(regex, line)
+ if matches:
+ max_write_bytes = max(max_write_bytes, int(matches.group(1)))
+ continue
for k in sorted(timings):
timings_ar = timings[k]
print "%s: %s avg: %s" % (k, timings_ar, sum(timings_ar) / float(len(timings_ar)) )
+
+ print "\nAdditional stats: "
+ print " max write_bytes: %d" % max_write_bytes
+
if __name__ == '__main__':
main()
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index bc2b9a632b72..1cb0ecdba7f3 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -753,7 +753,7 @@ public class LinkPropertiesTest extends TestCase {
@SmallTest
public void testCompareResult() {
// Either adding or removing items
- testCompareResult(Arrays.asList(1), Arrays.asList(1, 2, 3, 4),
+ testCompareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
Arrays.asList(2, 3, 4), new ArrayList<>());
testCompareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4),
new ArrayList<>(), Arrays.asList(3, 4));
@@ -780,9 +780,9 @@ public class LinkPropertiesTest extends TestCase {
assertEquals(expectedSet, actualSet);
}
- private <T> void testCompareResult(List<T> oldItems, List<T> newItems, List<T> expectAdded,
- List<T> expectRemoved) {
- CompareResult<T> result = new CompareResult<>(newItems, oldItems);
+ private <T> void testCompareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
+ List<T> expectAdded) {
+ CompareResult<T> result = new CompareResult<>(oldItems, newItems);
assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added));
assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed)));
}
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 10d3e05c067f..4b80542ad0d0 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -558,6 +558,16 @@ public:
SkPaint* getPaint();
void syncProperties() {
if (mStagingProperties.mNonAnimatablePropertiesDirty) {
+ mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth
+ != mStagingProperties.mNonAnimatableProperties.viewportWidth)
+ || (mProperties.mNonAnimatableProperties.viewportHeight
+ != mStagingProperties.mNonAnimatableProperties.viewportHeight)
+ || (mProperties.mNonAnimatableProperties.scaledWidth
+ != mStagingProperties.mNonAnimatableProperties.scaledWidth)
+ || (mProperties.mNonAnimatableProperties.scaledHeight
+ != mStagingProperties.mNonAnimatableProperties.scaledHeight)
+ || (mProperties.mNonAnimatableProperties.bounds
+ != mStagingProperties.mNonAnimatableProperties.bounds);
mProperties.syncNonAnimatableProperties(mStagingProperties);
mStagingProperties.mNonAnimatablePropertiesDirty = false;
}
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 3a77195824ad..afb1193657e1 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -40,7 +40,7 @@ static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong"
constexpr int sHistogramSize = ProfileData::HistogramSize();
-static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
+static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
const std::string& package, int versionCode, int64_t startTime, int64_t endTime,
const ProfileData* data);
static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
@@ -159,7 +159,7 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, service::Graph
return success;
}
-void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
+bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
proto->set_stats_start(startTime);
@@ -188,23 +188,31 @@ void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st
proto->mutable_histogram()->Reserve(sHistogramSize);
creatingHistogram = true;
} else if (proto->histogram_size() != sHistogramSize) {
- LOG_ALWAYS_FATAL("Histogram size mismatch, proto is %d expected %d",
+ ALOGE("Histogram size mismatch, proto is %d expected %d",
proto->histogram_size(), sHistogramSize);
+ return false;
}
int index = 0;
+ bool hitMergeError = false;
data->histogramForEach([&](ProfileData::HistogramEntry entry) {
+ if (hitMergeError) return;
+
service::GraphicsStatsHistogramBucketProto* bucket;
if (creatingHistogram) {
bucket = proto->add_histogram();
bucket->set_render_millis(entry.renderTimeMs);
} else {
bucket = proto->mutable_histogram(index);
- LOG_ALWAYS_FATAL_IF(bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs),
- "Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+ if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
+ ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+ hitMergeError = true;
+ return;
+ }
}
bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
index++;
});
+ return !hitMergeError;
}
static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
@@ -221,9 +229,11 @@ static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile
void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
// This isn't a full validation, just enough that we can deref at will
- LOG_ALWAYS_FATAL_IF(proto->package_name().empty()
- || !proto->has_summary(), "package_name() '%s' summary %d",
- proto->package_name().c_str(), proto->has_summary());
+ if (proto->package_name().empty() || !proto->has_summary()) {
+ ALOGW("Skipping dump, invalid package_name() '%s' or summary %d",
+ proto->package_name().c_str(), proto->has_summary());
+ return;
+ }
dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
dprintf(fd, "\nVersion: %d", proto->version_code());
dprintf(fd, "\nStats since: %lldns", proto->stats_start());
@@ -254,14 +264,20 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string
if (!parseFromFile(path, &statsProto)) {
statsProto.Clear();
}
- mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+ if (!mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) {
+ return;
+ }
// Although we might not have read any data from the file, merging the existing data
// should always fully-initialize the proto
- LOG_ALWAYS_FATAL_IF(!statsProto.IsInitialized(), "%s",
- statsProto.InitializationErrorString().c_str());
- LOG_ALWAYS_FATAL_IF(statsProto.package_name().empty()
- || !statsProto.has_summary(), "package_name() '%s' summary %d",
- statsProto.package_name().c_str(), statsProto.has_summary());
+ if (!statsProto.IsInitialized()) {
+ ALOGE("proto initialization error %s", statsProto.InitializationErrorString().c_str());
+ return;
+ }
+ if (statsProto.package_name().empty() || !statsProto.has_summary()) {
+ ALOGE("missing package_name() '%s' summary %d",
+ statsProto.package_name().c_str(), statsProto.has_summary());
+ return;
+ }
int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660);
if (outFd <= 0) {
int err = errno;
@@ -312,8 +328,9 @@ void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, const
if (!path.empty() && !parseFromFile(path, &statsProto)) {
statsProto.Clear();
}
- if (data) {
- mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+ if (data && !mergeProfileDataIntoProto(
+ &statsProto, package, versionCode, startTime, endTime, data)) {
+ return;
}
if (!statsProto.IsInitialized()) {
ALOGW("Failed to load profile data from path '%s' and data %p",
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index f85925d8d867..f41e33f7c102 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2749,8 +2749,8 @@ public final class MediaCodecInfo {
mQualityRange = Utils
.parseIntRange(info.getString("quality-range"), mQualityRange);
}
- if (info.containsKey("feature-bitrate-control")) {
- for (String mode: info.getString("feature-bitrate-control").split(",")) {
+ if (info.containsKey("feature-bitrate-modes")) {
+ for (String mode: info.getString("feature-bitrate-modes").split(",")) {
mBitControl |= parseBitrateMode(mode);
}
}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index fe427a73bf96..8707ad017f51 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -204,7 +204,6 @@ public class MediaRouter {
audioRoutesChanged = true;
}
- final int mainType = mCurAudioRoutesInfo.mainType;
if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
if (mCurAudioRoutesInfo.bluetoothName != null) {
@@ -231,8 +230,11 @@ public class MediaRouter {
}
if (audioRoutesChanged) {
- selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false);
Log.v(TAG, "Audio routes updated: " + newRoutes + ", a2dp=" + isBluetoothA2dpOn());
+ if (mSelectedRoute == null || mSelectedRoute == mDefaultAudioVideo
+ || mSelectedRoute == mBluetoothA2dpRoute) {
+ selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false);
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 9b75c00aeb3a..35ba6ae975d8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -26,7 +26,6 @@ import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -320,6 +319,15 @@ public class TileUtils {
Context context, UserHandle user, Intent intent,
Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon) {
+ getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
+ usePriority, checkCategory, forceTintExternalIcon, false /* shouldUpdateTiles */);
+ }
+
+ public static void getTilesForIntent(
+ Context context, UserHandle user, Intent intent,
+ Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
+ boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon,
+ boolean shouldUpdateTiles) {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
PackageManager.GET_META_DATA, user.getIdentifier());
@@ -357,9 +365,11 @@ public class TileUtils {
updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
pm, providerMap, forceTintExternalIcon);
if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
-
addedCache.put(key, tile);
+ } else if (shouldUpdateTiles) {
+ updateSummaryAndTitle(context, providerMap, tile);
}
+
if (!tile.userHandle.contains(user)) {
tile.userHandle.add(user);
}
@@ -380,7 +390,6 @@ public class TileUtils {
String summary = null;
String keyHint = null;
boolean isIconTintable = false;
- RemoteViews remoteViews = null;
// Get the activity's meta-data
try {
@@ -428,7 +437,8 @@ public class TileUtils {
}
if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) {
int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW);
- remoteViews = new RemoteViews(applicationInfo.packageName, layoutId);
+ tile.remoteViews = new RemoteViews(applicationInfo.packageName, layoutId);
+ updateSummaryAndTitle(context, providerMap, tile);
}
}
} catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
@@ -462,7 +472,6 @@ public class TileUtils {
// Suggest a key for this tile
tile.key = keyHint;
tile.isIconTintable = isIconTintable;
- tile.remoteViews = remoteViews;
return true;
}
@@ -470,6 +479,26 @@ public class TileUtils {
return false;
}
+ private static void updateSummaryAndTitle(
+ Context context, Map<String, IContentProvider> providerMap, Tile tile) {
+ if (tile == null || tile.metaData == null
+ || !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
+ return;
+ }
+
+ String uriString = tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI);
+ Bundle bundle = getBundleFromUri(context, uriString, providerMap);
+ String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY);
+ String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE);
+ if (overrideSummary != null) {
+ tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
+ }
+
+ if (overrideTitle != null) {
+ tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle);
+ }
+ }
+
/**
* Gets the icon package name and resource id from content provider.
* @param context context
@@ -535,37 +564,6 @@ public class TileUtils {
}
}
- public static void updateTileUsingSummaryUri(Context context, final Tile tile) {
- if (tile == null || tile.metaData == null ||
- !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
- return;
- }
-
- new AsyncTask<Void, Void, Bundle>() {
- @Override
- protected Bundle doInBackground(Void... params) {
- return getBundleFromUri(context,
- tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI), new HashMap<>());
- }
-
- @Override
- protected void onPostExecute(Bundle bundle) {
- if (bundle == null) {
- return;
- }
- final String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY);
- final String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE);
-
- if (overrideSummary != null) {
- tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
- }
- if (overrideTitle != null) {
- tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle);
- }
- }
- }.execute();
- }
-
private static String getString(Bundle bundle, String key) {
return bundle == null ? null : bundle.getString(key);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
index 00f32b2839af..56b84415e907 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
@@ -195,7 +195,7 @@ public class SuggestionParser {
intent.setPackage(category.pkg);
}
TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
- mAddCache, null, suggestions, true, false, false);
+ mAddCache, null, suggestions, true, false, false, true /* shouldUpdateTiles */);
filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
if (!category.multiple && suggestions.size() > (countBefore + 1)) {
// If there are too many, remove them all and only re-add the one with the highest
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 76f6a20959fb..3e90435b21d7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -22,12 +22,10 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
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 static org.robolectric.RuntimeEnvironment.application;
@@ -66,7 +64,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.internal.ShadowExtractor;
import java.util.ArrayList;
import java.util.Collections;
@@ -75,7 +75,8 @@ import java.util.Map;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
- sdk = TestConfig.SDK_VERSION)
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {TileUtilsTest.TileUtilsShadowRemoteViews.class})
public class TileUtilsTest {
@Mock
@@ -420,12 +421,24 @@ public class TileUtilsTest {
}
@Test
- public void updateTileUsingSummaryUri_summaryUriSpecified_shouldOverrideRemoteViewSummary()
+ public void getTilesForIntent_summaryUriSpecified_shouldOverrideRemoteViewSummary()
throws RemoteException {
+ Intent intent = new Intent();
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null,
+ null, URI_GET_SUMMARY);
+ resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
+ R.layout.user_preference);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+ .thenReturn(info);
+
// Mock the content provider interaction.
Bundle bundle = new Bundle();
- String expectedSummary = "new summary text";
- bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, expectedSummary);
+ bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text");
when(mIContentProvider.call(anyString(),
eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
any())).thenReturn(bundle);
@@ -434,14 +447,57 @@ public class TileUtilsTest {
when(mContentResolver.acquireUnstableProvider(any(Uri.class)))
.thenReturn(mIContentProvider);
- Tile tile = new Tile();
- tile.metaData = new Bundle();
- tile.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY);
- tile.remoteViews = mock(RemoteViews.class);
- TileUtils.updateTileUsingSummaryUri(mContext, tile);
- ShadowApplication.runBackgroundTasks();
+ TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+ null /* defaultCategory */, outTiles, false /* usePriority */,
+ false /* checkCategory */, true /* forceTintExternalIcon */);
- verify(tile.remoteViews, times(1)).setTextViewText(anyInt(), eq(expectedSummary));
+ assertThat(outTiles.size()).isEqualTo(1);
+ Tile tile = outTiles.get(0);
+ assertThat(tile.remoteViews).isNotNull();
+ assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
+ // Make sure the summary TextView got a new text string.
+ TileUtilsShadowRemoteViews shadowRemoteViews =
+ (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews);
+ assertThat(shadowRemoteViews.overrideViewId).isEqualTo(android.R.id.summary);
+ assertThat(shadowRemoteViews.overrideText).isEqualTo("new summary text");
+ }
+
+ @Test
+ public void getTilesForIntent_providerUnavailable_shouldNotOverrideRemoteViewSummary()
+ throws RemoteException {
+ Intent intent = new Intent();
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null,
+ null, URI_GET_SUMMARY);
+ resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
+ R.layout.user_preference);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+ .thenReturn(info);
+
+ // Mock the content provider interaction.
+ Bundle bundle = new Bundle();
+ bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text");
+ when(mIContentProvider.call(anyString(),
+ eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
+ any())).thenReturn(bundle);
+
+ TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+ null /* defaultCategory */, outTiles, false /* usePriority */,
+ false /* checkCategory */, true /* forceTintExternalIcon */);
+
+ assertThat(outTiles.size()).isEqualTo(1);
+ Tile tile = outTiles.get(0);
+ assertThat(tile.remoteViews).isNotNull();
+ assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
+ // Make sure the summary TextView didn't get any text view updates.
+ TileUtilsShadowRemoteViews shadowRemoteViews =
+ (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews);
+ assertThat(shadowRemoteViews.overrideViewId).isNull();
+ assertThat(shadowRemoteViews.overrideText).isNull();
}
public static ResolveInfo newInfo(boolean systemApp, String category) {
@@ -502,4 +558,16 @@ public class TileUtilsTest {
}
}
+ @Implements(RemoteViews.class)
+ public static class TileUtilsShadowRemoteViews {
+
+ private Integer overrideViewId;
+ private CharSequence overrideText;
+
+ @Implementation
+ public void setTextViewText(int viewId, CharSequence text) {
+ overrideViewId = viewId;
+ overrideText = text;
+ }
+ }
}
diff --git a/packages/SettingsProvider/res/values-af/defaults.xml b/packages/SettingsProvider/res/values-af/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-af/defaults.xml
+++ b/packages/SettingsProvider/res/values-af/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-am/defaults.xml b/packages/SettingsProvider/res/values-am/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-am/defaults.xml
+++ b/packages/SettingsProvider/res/values-am/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ar/defaults.xml b/packages/SettingsProvider/res/values-ar/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ar/defaults.xml
+++ b/packages/SettingsProvider/res/values-ar/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-az/defaults.xml b/packages/SettingsProvider/res/values-az/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-az/defaults.xml
+++ b/packages/SettingsProvider/res/values-az/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml b/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml
index 524132e57827..16aed2ec05a3 100644
--- a/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml
+++ b/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-be/defaults.xml b/packages/SettingsProvider/res/values-be/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-be/defaults.xml
+++ b/packages/SettingsProvider/res/values-be/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-bg/defaults.xml b/packages/SettingsProvider/res/values-bg/defaults.xml
index 715e78f83391..7a4c28c65a97 100644
--- a/packages/SettingsProvider/res/values-bg/defaults.xml
+++ b/packages/SettingsProvider/res/values-bg/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s от %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-bn/defaults.xml b/packages/SettingsProvider/res/values-bn/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-bn/defaults.xml
+++ b/packages/SettingsProvider/res/values-bn/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-bs/defaults.xml b/packages/SettingsProvider/res/values-bs/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-bs/defaults.xml
+++ b/packages/SettingsProvider/res/values-bs/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ca/defaults.xml b/packages/SettingsProvider/res/values-ca/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ca/defaults.xml
+++ b/packages/SettingsProvider/res/values-ca/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-cs/defaults.xml b/packages/SettingsProvider/res/values-cs/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-cs/defaults.xml
+++ b/packages/SettingsProvider/res/values-cs/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-da/defaults.xml b/packages/SettingsProvider/res/values-da/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-da/defaults.xml
+++ b/packages/SettingsProvider/res/values-da/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-de/defaults.xml b/packages/SettingsProvider/res/values-de/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-de/defaults.xml
+++ b/packages/SettingsProvider/res/values-de/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-el/defaults.xml b/packages/SettingsProvider/res/values-el/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-el/defaults.xml
+++ b/packages/SettingsProvider/res/values-el/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rAU/defaults.xml b/packages/SettingsProvider/res/values-en-rAU/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-en-rAU/defaults.xml
+++ b/packages/SettingsProvider/res/values-en-rAU/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rCA/defaults.xml b/packages/SettingsProvider/res/values-en-rCA/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-en-rCA/defaults.xml
+++ b/packages/SettingsProvider/res/values-en-rCA/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/defaults.xml b/packages/SettingsProvider/res/values-en-rGB/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-en-rGB/defaults.xml
+++ b/packages/SettingsProvider/res/values-en-rGB/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rIN/defaults.xml b/packages/SettingsProvider/res/values-en-rIN/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-en-rIN/defaults.xml
+++ b/packages/SettingsProvider/res/values-en-rIN/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rXC/defaults.xml b/packages/SettingsProvider/res/values-en-rXC/defaults.xml
index b32199f372dc..34f63e7abebf 100644
--- a/packages/SettingsProvider/res/values-en-rXC/defaults.xml
+++ b/packages/SettingsProvider/res/values-en-rXC/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎%1$s %2$s‎‏‎‎‏‎"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎%1$s‎‏‎‎‏‎"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/defaults.xml b/packages/SettingsProvider/res/values-es-rUS/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-es-rUS/defaults.xml
+++ b/packages/SettingsProvider/res/values-es-rUS/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-es/defaults.xml b/packages/SettingsProvider/res/values-es/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-es/defaults.xml
+++ b/packages/SettingsProvider/res/values-es/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-et/defaults.xml b/packages/SettingsProvider/res/values-et/defaults.xml
index 5ec05cb5688e..37dab156c59f 100644
--- a/packages/SettingsProvider/res/values-et/defaults.xml
+++ b/packages/SettingsProvider/res/values-et/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s, %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-eu/defaults.xml b/packages/SettingsProvider/res/values-eu/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-eu/defaults.xml
+++ b/packages/SettingsProvider/res/values-eu/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fa/defaults.xml b/packages/SettingsProvider/res/values-fa/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-fa/defaults.xml
+++ b/packages/SettingsProvider/res/values-fa/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fi/defaults.xml b/packages/SettingsProvider/res/values-fi/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-fi/defaults.xml
+++ b/packages/SettingsProvider/res/values-fi/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fr-rCA/defaults.xml b/packages/SettingsProvider/res/values-fr-rCA/defaults.xml
index b7280139184a..f439312cbfe9 100644
--- a/packages/SettingsProvider/res/values-fr-rCA/defaults.xml
+++ b/packages/SettingsProvider/res/values-fr-rCA/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s de %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fr/defaults.xml b/packages/SettingsProvider/res/values-fr/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-fr/defaults.xml
+++ b/packages/SettingsProvider/res/values-fr/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-gl/defaults.xml b/packages/SettingsProvider/res/values-gl/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-gl/defaults.xml
+++ b/packages/SettingsProvider/res/values-gl/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-gu/defaults.xml b/packages/SettingsProvider/res/values-gu/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-gu/defaults.xml
+++ b/packages/SettingsProvider/res/values-gu/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hi/defaults.xml b/packages/SettingsProvider/res/values-hi/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-hi/defaults.xml
+++ b/packages/SettingsProvider/res/values-hi/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hr/defaults.xml b/packages/SettingsProvider/res/values-hr/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-hr/defaults.xml
+++ b/packages/SettingsProvider/res/values-hr/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hu/defaults.xml b/packages/SettingsProvider/res/values-hu/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-hu/defaults.xml
+++ b/packages/SettingsProvider/res/values-hu/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hy/defaults.xml b/packages/SettingsProvider/res/values-hy/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-hy/defaults.xml
+++ b/packages/SettingsProvider/res/values-hy/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-in/defaults.xml b/packages/SettingsProvider/res/values-in/defaults.xml
index 71f1d3b1569d..a63de85206eb 100644
--- a/packages/SettingsProvider/res/values-in/defaults.xml
+++ b/packages/SettingsProvider/res/values-in/defaults.xml
@@ -24,4 +24,5 @@
<!-- no translation found for def_device_name_simple (9037785625140748221) -->
<skip />
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-is/defaults.xml b/packages/SettingsProvider/res/values-is/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-is/defaults.xml
+++ b/packages/SettingsProvider/res/values-is/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-it/defaults.xml b/packages/SettingsProvider/res/values-it/defaults.xml
index 524132e57827..16aed2ec05a3 100644
--- a/packages/SettingsProvider/res/values-it/defaults.xml
+++ b/packages/SettingsProvider/res/values-it/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-iw/defaults.xml b/packages/SettingsProvider/res/values-iw/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-iw/defaults.xml
+++ b/packages/SettingsProvider/res/values-iw/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ja/defaults.xml b/packages/SettingsProvider/res/values-ja/defaults.xml
index 524132e57827..16aed2ec05a3 100644
--- a/packages/SettingsProvider/res/values-ja/defaults.xml
+++ b/packages/SettingsProvider/res/values-ja/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ka/defaults.xml b/packages/SettingsProvider/res/values-ka/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ka/defaults.xml
+++ b/packages/SettingsProvider/res/values-ka/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-kk/defaults.xml b/packages/SettingsProvider/res/values-kk/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-kk/defaults.xml
+++ b/packages/SettingsProvider/res/values-kk/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-km/defaults.xml b/packages/SettingsProvider/res/values-km/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-km/defaults.xml
+++ b/packages/SettingsProvider/res/values-km/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-kn/defaults.xml b/packages/SettingsProvider/res/values-kn/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-kn/defaults.xml
+++ b/packages/SettingsProvider/res/values-kn/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ko/defaults.xml b/packages/SettingsProvider/res/values-ko/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ko/defaults.xml
+++ b/packages/SettingsProvider/res/values-ko/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ky/defaults.xml b/packages/SettingsProvider/res/values-ky/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ky/defaults.xml
+++ b/packages/SettingsProvider/res/values-ky/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-lo/defaults.xml b/packages/SettingsProvider/res/values-lo/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-lo/defaults.xml
+++ b/packages/SettingsProvider/res/values-lo/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-lt/defaults.xml b/packages/SettingsProvider/res/values-lt/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-lt/defaults.xml
+++ b/packages/SettingsProvider/res/values-lt/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-lv/defaults.xml b/packages/SettingsProvider/res/values-lv/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-lv/defaults.xml
+++ b/packages/SettingsProvider/res/values-lv/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-mk/defaults.xml b/packages/SettingsProvider/res/values-mk/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-mk/defaults.xml
+++ b/packages/SettingsProvider/res/values-mk/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ml/defaults.xml b/packages/SettingsProvider/res/values-ml/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ml/defaults.xml
+++ b/packages/SettingsProvider/res/values-ml/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-mn/defaults.xml b/packages/SettingsProvider/res/values-mn/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-mn/defaults.xml
+++ b/packages/SettingsProvider/res/values-mn/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-mr/defaults.xml b/packages/SettingsProvider/res/values-mr/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-mr/defaults.xml
+++ b/packages/SettingsProvider/res/values-mr/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ms/defaults.xml b/packages/SettingsProvider/res/values-ms/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ms/defaults.xml
+++ b/packages/SettingsProvider/res/values-ms/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-my/defaults.xml b/packages/SettingsProvider/res/values-my/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-my/defaults.xml
+++ b/packages/SettingsProvider/res/values-my/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-nb/defaults.xml b/packages/SettingsProvider/res/values-nb/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-nb/defaults.xml
+++ b/packages/SettingsProvider/res/values-nb/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ne/defaults.xml b/packages/SettingsProvider/res/values-ne/defaults.xml
index 71f1d3b1569d..a63de85206eb 100644
--- a/packages/SettingsProvider/res/values-ne/defaults.xml
+++ b/packages/SettingsProvider/res/values-ne/defaults.xml
@@ -24,4 +24,5 @@
<!-- no translation found for def_device_name_simple (9037785625140748221) -->
<skip />
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-nl/defaults.xml b/packages/SettingsProvider/res/values-nl/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-nl/defaults.xml
+++ b/packages/SettingsProvider/res/values-nl/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pa/defaults.xml b/packages/SettingsProvider/res/values-pa/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-pa/defaults.xml
+++ b/packages/SettingsProvider/res/values-pa/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pl/defaults.xml b/packages/SettingsProvider/res/values-pl/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-pl/defaults.xml
+++ b/packages/SettingsProvider/res/values-pl/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rBR/defaults.xml b/packages/SettingsProvider/res/values-pt-rBR/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-pt-rBR/defaults.xml
+++ b/packages/SettingsProvider/res/values-pt-rBR/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
+++ b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pt/defaults.xml b/packages/SettingsProvider/res/values-pt/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-pt/defaults.xml
+++ b/packages/SettingsProvider/res/values-pt/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ro/defaults.xml b/packages/SettingsProvider/res/values-ro/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ro/defaults.xml
+++ b/packages/SettingsProvider/res/values-ro/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ru/defaults.xml b/packages/SettingsProvider/res/values-ru/defaults.xml
index 524132e57827..16aed2ec05a3 100644
--- a/packages/SettingsProvider/res/values-ru/defaults.xml
+++ b/packages/SettingsProvider/res/values-ru/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-si/defaults.xml b/packages/SettingsProvider/res/values-si/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-si/defaults.xml
+++ b/packages/SettingsProvider/res/values-si/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sk/defaults.xml b/packages/SettingsProvider/res/values-sk/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-sk/defaults.xml
+++ b/packages/SettingsProvider/res/values-sk/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sl/defaults.xml b/packages/SettingsProvider/res/values-sl/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-sl/defaults.xml
+++ b/packages/SettingsProvider/res/values-sl/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sq/defaults.xml b/packages/SettingsProvider/res/values-sq/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-sq/defaults.xml
+++ b/packages/SettingsProvider/res/values-sq/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sr/defaults.xml b/packages/SettingsProvider/res/values-sr/defaults.xml
index 524132e57827..16aed2ec05a3 100644
--- a/packages/SettingsProvider/res/values-sr/defaults.xml
+++ b/packages/SettingsProvider/res/values-sr/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sv/defaults.xml b/packages/SettingsProvider/res/values-sv/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-sv/defaults.xml
+++ b/packages/SettingsProvider/res/values-sv/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sw/defaults.xml b/packages/SettingsProvider/res/values-sw/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-sw/defaults.xml
+++ b/packages/SettingsProvider/res/values-sw/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ta/defaults.xml b/packages/SettingsProvider/res/values-ta/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ta/defaults.xml
+++ b/packages/SettingsProvider/res/values-ta/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-te/defaults.xml b/packages/SettingsProvider/res/values-te/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-te/defaults.xml
+++ b/packages/SettingsProvider/res/values-te/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-th/defaults.xml b/packages/SettingsProvider/res/values-th/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-th/defaults.xml
+++ b/packages/SettingsProvider/res/values-th/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-tl/defaults.xml b/packages/SettingsProvider/res/values-tl/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-tl/defaults.xml
+++ b/packages/SettingsProvider/res/values-tl/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-tr/defaults.xml b/packages/SettingsProvider/res/values-tr/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-tr/defaults.xml
+++ b/packages/SettingsProvider/res/values-tr/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-uk/defaults.xml b/packages/SettingsProvider/res/values-uk/defaults.xml
index a8e1fe819184..71b29ef66489 100644
--- a/packages/SettingsProvider/res/values-uk/defaults.xml
+++ b/packages/SettingsProvider/res/values-uk/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%2$s о %1$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ur/defaults.xml b/packages/SettingsProvider/res/values-ur/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-ur/defaults.xml
+++ b/packages/SettingsProvider/res/values-ur/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-uz/defaults.xml b/packages/SettingsProvider/res/values-uz/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-uz/defaults.xml
+++ b/packages/SettingsProvider/res/values-uz/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-vi/defaults.xml b/packages/SettingsProvider/res/values-vi/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-vi/defaults.xml
+++ b/packages/SettingsProvider/res/values-vi/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
+++ b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rHK/defaults.xml b/packages/SettingsProvider/res/values-zh-rHK/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-zh-rHK/defaults.xml
+++ b/packages/SettingsProvider/res/values-zh-rHK/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
+++ b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zu/defaults.xml b/packages/SettingsProvider/res/values-zu/defaults.xml
index 4a87a1250404..2b8033c98c5f 100644
--- a/packages/SettingsProvider/res/values-zu/defaults.xml
+++ b/packages/SettingsProvider/res/values-zu/defaults.xml
@@ -22,4 +22,5 @@
<string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
<string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
<string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+ <string name="def_backup_manager_constants" msgid="75273734665044867"></string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 8de1d317c5ed..2bc0e45c725d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -15,6 +15,8 @@
*/
package com.android.keyguard;
+import static android.view.Display.INVALID_DISPLAY;
+
import android.app.Presentation;
import android.content.Context;
import android.content.DialogInterface;
@@ -28,16 +30,21 @@ import android.view.Display;
import android.view.View;
import android.view.WindowManager;
+// TODO(multi-display): Support multiple external displays
public class KeyguardDisplayManager {
protected static final String TAG = "KeyguardDisplayManager";
private static boolean DEBUG = KeyguardConstants.DEBUG;
+
+ private final ViewMediatorCallback mCallback;
+ private final MediaRouter mMediaRouter;
+ private final Context mContext;
+
Presentation mPresentation;
- private MediaRouter mMediaRouter;
- private Context mContext;
private boolean mShowing;
- public KeyguardDisplayManager(Context context) {
+ public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) {
mContext = context;
+ mCallback = callback;
mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
}
@@ -90,6 +97,7 @@ public class KeyguardDisplayManager {
};
protected void updateDisplays(boolean showing) {
+ Presentation originalPresentation = mPresentation;
if (showing) {
MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
@@ -121,6 +129,13 @@ public class KeyguardDisplayManager {
mPresentation = null;
}
}
+
+ // mPresentation is only updated when the display changes
+ if (mPresentation != originalPresentation) {
+ final int displayId = mPresentation != null
+ ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY;
+ mCallback.onSecondaryDisplayShowingChanged(displayId);
+ }
}
private final static class KeyguardPresentation extends Presentation {
diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
index 327d218913d2..b194de43a718 100644
--- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
@@ -88,4 +88,9 @@ public interface ViewMediatorCallback {
* {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}.
*/
int getBouncerPromptReason();
+
+ /**
+ * Invoked when the secondary display showing a keyguard window changes.
+ */
+ void onSecondaryDisplayShowingChanged(int displayId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 4cbbbd6c2e90..189badfc42fc 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1280,7 +1280,23 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
mGradientDrawable.setScreenSize(displaySize.x, displaySize.y);
GradientColors colors = mColorExtractor.getColors(mKeyguardShowing ?
WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
- mGradientDrawable.setColors(colors, false);
+ updateColors(colors, false /* animate */);
+ }
+
+ /**
+ * Updates background and system bars according to current GradientColors.
+ * @param colors Colors and hints to use.
+ * @param animate Interpolates gradient if true, just sets otherwise.
+ */
+ private void updateColors(GradientColors colors, boolean animate) {
+ mGradientDrawable.setColors(colors, animate);
+ View decorView = getWindow().getDecorView();
+ if (colors.supportsDarkText()) {
+ decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
+ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ } else {
+ decorView.setSystemUiVisibility(0);
+ }
}
@Override
@@ -1350,11 +1366,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
public void onColorsChanged(ColorExtractor extractor, int which) {
if (mKeyguardShowing) {
if ((WallpaperManager.FLAG_LOCK & which) != 0) {
- mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_LOCK));
+ updateColors(extractor.getColors(WallpaperManager.FLAG_LOCK),
+ true /* animate */);
}
} else {
if ((WallpaperManager.FLAG_SYSTEM & which) != 0) {
- mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM));
+ updateColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM),
+ true /* animate */);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3eb68f5214c0..28adca97b8bf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.telephony.IccCardConstants.State.ABSENT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
@@ -239,6 +240,9 @@ public class KeyguardViewMediator extends SystemUI {
// answer whether the input should be restricted)
private boolean mShowing;
+ // display id of the secondary display on which we have put a keyguard window
+ private int mSecondaryDisplayShowing = INVALID_DISPLAY;
+
/** Cached value of #isInputRestricted */
private boolean mInputRestricted;
@@ -646,6 +650,13 @@ public class KeyguardViewMediator extends SystemUI {
}
return KeyguardSecurityView.PROMPT_REASON_NONE;
}
+
+ @Override
+ public void onSecondaryDisplayShowingChanged(int displayId) {
+ synchronized (KeyguardViewMediator.this) {
+ setShowingLocked(mShowing, displayId, false);
+ }
+ }
};
public void userActivity() {
@@ -670,7 +681,7 @@ public class KeyguardViewMediator extends SystemUI {
filter.addAction(Intent.ACTION_SHUTDOWN);
mContext.registerReceiver(mBroadcastReceiver, filter);
- mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);
+ mKeyguardDisplayManager = new KeyguardDisplayManager(mContext, mViewMediatorCallback);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
@@ -685,7 +696,8 @@ public class KeyguardViewMediator extends SystemUI {
com.android.keyguard.R.bool.config_enableKeyguardService)) {
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
- KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
+ KeyguardUpdateMonitor.getCurrentUser()),
+ mSecondaryDisplayShowing, true /* forceCallbacks */);
}
mStatusBarKeyguardViewManager =
@@ -1694,10 +1706,10 @@ public class KeyguardViewMediator extends SystemUI {
playSound(mTrustedSoundId);
}
- private void updateActivityLockScreenState(boolean showing) {
+ private void updateActivityLockScreenState(boolean showing, int secondaryDisplayShowing) {
mUiOffloadThread.submit(() -> {
try {
- ActivityManager.getService().setLockScreenShown(showing);
+ ActivityManager.getService().setLockScreenShown(showing, secondaryDisplayShowing);
} catch (RemoteException e) {
}
});
@@ -2060,30 +2072,39 @@ public class KeyguardViewMediator extends SystemUI {
}
private void setShowingLocked(boolean showing) {
- setShowingLocked(showing, false /* forceCallbacks */);
+ setShowingLocked(showing, mSecondaryDisplayShowing, false /* forceCallbacks */);
}
- private void setShowingLocked(boolean showing, boolean forceCallbacks) {
- if (showing != mShowing || forceCallbacks) {
+ private void setShowingLocked(
+ boolean showing, int secondaryDisplayShowing, boolean forceCallbacks) {
+ final boolean notifyDefaultDisplayCallbacks = showing != mShowing || forceCallbacks;
+ if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) {
mShowing = showing;
- int size = mKeyguardStateCallbacks.size();
- for (int i = size - 1; i >= 0; i--) {
- IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
- try {
- callback.onShowingStateChanged(showing);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onShowingStateChanged", e);
- if (e instanceof DeadObjectException) {
- mKeyguardStateCallbacks.remove(callback);
- }
+ mSecondaryDisplayShowing = secondaryDisplayShowing;
+ if (notifyDefaultDisplayCallbacks) {
+ notifyDefaultDisplayCallbacks(showing);
+ }
+ updateActivityLockScreenState(showing, secondaryDisplayShowing);
+ }
+ }
+
+ private void notifyDefaultDisplayCallbacks(boolean showing) {
+ int size = mKeyguardStateCallbacks.size();
+ for (int i = size - 1; i >= 0; i--) {
+ IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
+ try {
+ callback.onShowingStateChanged(showing);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onShowingStateChanged", e);
+ if (e instanceof DeadObjectException) {
+ mKeyguardStateCallbacks.remove(callback);
}
}
- updateInputRestrictedLocked();
- mUiOffloadThread.submit(() -> {
- mTrustManager.reportKeyguardShowingChanged();
- });
- updateActivityLockScreenState(showing);
}
+ updateInputRestrictedLocked();
+ mUiOffloadThread.submit(() -> {
+ mTrustManager.reportKeyguardShowingChanged();
+ });
}
private void notifyTrustedChangedLocked(boolean trusted) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index aecf95fc677f..c4e870135a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -565,8 +565,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Launch the task
ssp.startActivityFromRecents(
- mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
- null /* resultListener */);
+ mContext, toTask.key, toTask.title, launchOpts, null /* resultListener */);
}
/**
@@ -639,8 +638,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Launch the task
ssp.startActivityFromRecents(
- mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
- null /* resultListener */);
+ mContext, toTask.key, toTask.title, launchOpts, null /* resultListener */);
}
public void showNextAffiliatedTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
index 3db106e7200f..862a1eee8c39 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
@@ -16,6 +16,9 @@
package com.android.systemui.recents.events.activity;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.graphics.Rect;
import com.android.systemui.recents.events.EventBus;
@@ -30,15 +33,23 @@ public class LaunchTaskEvent extends EventBus.Event {
public final TaskView taskView;
public final Task task;
public final Rect targetTaskBounds;
- public final int targetTaskStack;
+ public final int targetWindowingMode;
+ public final int targetActivityType;
public final boolean screenPinningRequested;
- public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds, int targetTaskStack,
+ public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds,
boolean screenPinningRequested) {
+ this(taskView, task, targetTaskBounds, screenPinningRequested,
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED);
+ }
+
+ public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds,
+ boolean screenPinningRequested, int windowingMode, int activityType) {
this.taskView = taskView;
this.task = task;
this.targetTaskBounds = targetTaskBounds;
- this.targetTaskStack = targetTaskStack;
+ this.targetWindowingMode = windowingMode;
+ this.targetActivityType = activityType;
this.screenPinningRequested = screenPinningRequested;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 717778228989..366a908f15bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -23,6 +23,10 @@ import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import android.annotation.NonNull;
@@ -576,7 +580,7 @@ public class SystemServicesProxy {
try {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setDockCreateMode(createMode);
- options.setLaunchStackId(DOCKED_STACK_ID);
+ options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mIam.startActivityFromRecents(taskId, options.toBundle());
return true;
} catch (Exception e) {
@@ -1120,9 +1124,16 @@ public class SystemServicesProxy {
opts != null ? opts.toBundle() : null, UserHandle.CURRENT));
}
+ public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
+ ActivityOptions options,
+ @Nullable final StartActivityFromRecentsResultListener resultListener) {
+ startActivityFromRecents(context, taskKey, taskName, options,
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED, resultListener);
+ }
+
/** Starts an activity from recents. */
public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
- ActivityOptions options, int stackId,
+ ActivityOptions options, int windowingMode, int activityType,
@Nullable final StartActivityFromRecentsResultListener resultListener) {
if (mIam == null) {
return;
@@ -1133,12 +1144,14 @@ public class SystemServicesProxy {
if (options == null) {
options = ActivityOptions.makeBasic();
}
- options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID);
- } else if (stackId != INVALID_STACK_ID) {
+ options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ } else if (windowingMode != WINDOWING_MODE_UNDEFINED
+ || activityType != ACTIVITY_TYPE_UNDEFINED) {
if (options == null) {
options = ActivityOptions.makeBasic();
}
- options.setLaunchStackId(stackId);
+ options.setLaunchWindowingMode(windowingMode);
+ options.setLaunchActivityType(activityType);
}
final ActivityOptions finalOptions = options;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index b2675d7ac858..4d3321638e8e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -21,6 +21,15 @@ import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.Nullable;
import android.app.ActivityManager.StackId;
@@ -107,7 +116,7 @@ public class RecentsTransitionHelper {
*/
public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
final TaskStackView stackView, final TaskView taskView,
- final boolean screenPinningRequested, final int destinationStack) {
+ final boolean screenPinningRequested, final int windowingMode, final int activityType) {
final ActivityOptions.OnAnimationStartedListener animStartedListener;
final AppTransitionAnimationSpecsFuture transitionFuture;
@@ -116,8 +125,8 @@ public class RecentsTransitionHelper {
// Fetch window rect here already in order not to be blocked on lock contention in WM
// when the future calls it.
final Rect windowRect = Recents.getSystemServices().getWindowRect();
- transitionFuture = getAppTransitionFuture(
- () -> composeAnimationSpecs(task, stackView, destinationStack, windowRect));
+ transitionFuture = getAppTransitionFuture(() -> composeAnimationSpecs(
+ task, stackView, windowingMode, activityType, windowRect));
animStartedListener = new OnAnimationStartedListener() {
private boolean mHandled;
@@ -180,7 +189,8 @@ public class RecentsTransitionHelper {
if (taskView == null) {
// If there is no task view, then we do not need to worry about animating out occluding
// task views, and we can launch immediately
- startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture,
+ windowingMode, activityType);
} else {
LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView,
screenPinningRequested);
@@ -189,13 +199,14 @@ public class RecentsTransitionHelper {
@Override
public void run() {
startTaskActivity(stack, task, taskView, opts, transitionFuture,
- destinationStack);
+ windowingMode, activityType);
}
});
EventBus.getDefault().send(launchStartedEvent);
} else {
EventBus.getDefault().send(launchStartedEvent);
- startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture,
+ windowingMode, activityType);
}
}
Recents.getSystemServices().sendCloseSystemWindows(
@@ -224,13 +235,13 @@ public class RecentsTransitionHelper {
*
* @param taskView this is the {@link TaskView} that we are launching from. This can be null if
* we are toggling recents and the launch-to task is now offscreen.
- * @param destinationStack id of the stack to put the task into.
*/
private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture,
- int destinationStack) {
+ int windowingMode, int activityType) {
SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack,
+ ssp.startActivityFromRecents(mContext, task.key, task.title, opts, windowingMode,
+ activityType,
succeeded -> {
if (succeeded) {
// Keep track of the index of the task launch
@@ -310,11 +321,9 @@ public class RecentsTransitionHelper {
* Composes the animation specs for all the tasks in the target stack.
*/
private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
- final TaskStackView stackView, final int destinationStack, Rect windowRect) {
- // Ensure we have a valid target stack id
- final int targetStackId = destinationStack != INVALID_STACK_ID ?
- destinationStack : task.key.stackId;
- if (!StackId.useAnimationSpecForAppTransition(targetStackId)) {
+ final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) {
+ if (activityType == ACTIVITY_TYPE_RECENTS || activityType == ACTIVITY_TYPE_HOME
+ || windowingMode == WINDOWING_MODE_PINNED) {
return null;
}
@@ -329,9 +338,12 @@ public class RecentsTransitionHelper {
List<AppTransitionAnimationSpec> specs = new ArrayList<>();
// TODO: Sometimes targetStackId is not initialized after reboot, so we also have to
- // check for INVALID_STACK_ID
- if (targetStackId == FULLSCREEN_WORKSPACE_STACK_ID || targetStackId == DOCKED_STACK_ID
- || targetStackId == ASSISTANT_STACK_ID || targetStackId == INVALID_STACK_ID) {
+ // check for INVALID_STACK_ID (now WINDOWING_MODE_UNDEFINED)
+ if (windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ || activityType == ACTIVITY_TYPE_ASSISTANT
+ || windowingMode == WINDOWING_MODE_UNDEFINED) {
if (taskView == null) {
specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
} else {
@@ -353,7 +365,7 @@ public class RecentsTransitionHelper {
int taskCount = tasks.size();
for (int i = taskCount - 1; i >= 0; i--) {
Task t = tasks.get(i);
- if (t.isFreeformTask() || targetStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (t.isFreeformTask() || windowingMode == WINDOWING_MODE_FREEFORM) {
TaskView tv = stackView.getChildViewForTask(t);
if (tv == null) {
// TODO: Create a different animation task rect for this case (though it should
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index c44cd7287625..fd1b806abf24 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -338,8 +338,7 @@ public class RecentsView extends FrameLayout {
Task task = mTaskStackView.getFocusedTask();
if (task != null) {
TaskView taskView = mTaskStackView.getChildViewForTask(task);
- EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
- INVALID_STACK_ID, false));
+ EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false));
if (logEvent != 0) {
MetricsLogger.action(getContext(), logEvent,
@@ -363,32 +362,13 @@ public class RecentsView extends FrameLayout {
Task task = getStack().getLaunchTarget();
if (task != null) {
TaskView taskView = mTaskStackView.getChildViewForTask(task);
- EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
- INVALID_STACK_ID, false));
+ EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false));
return true;
}
}
return false;
}
- /** Launches a given task. */
- public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
- if (mTaskStackView != null) {
- // Iterate the stack views and try and find the given task.
- List<TaskView> taskViews = mTaskStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int j = 0; j < taskViewCount; j++) {
- TaskView tv = taskViews.get(j);
- if (tv.getTask() == task) {
- EventBus.getDefault().send(new LaunchTaskEvent(tv, task, taskBounds,
- destinationStack, false));
- return true;
- }
- }
- }
- return false;
- }
-
/**
* Hides the task stack and shows the empty view.
*/
@@ -570,7 +550,8 @@ public class RecentsView extends FrameLayout {
public final void onBusEvent(LaunchTaskEvent event) {
mLastTaskLaunchedWasFreeform = event.task.isFreeformTask();
mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView,
- event.taskView, event.screenPinningRequested, event.targetTaskStack);
+ event.taskView, event.screenPinningRequested, event.targetWindowingMode,
+ event.targetActivityType);
if (Recents.getConfiguration().isLowRamDevice) {
hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, false /* translate */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 8899e307bb16..74e9ef2b3efb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1487,7 +1487,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Task frontTask = tasks.get(tasks.size() - 1);
if (frontTask != null && frontTask.isFreeformTask()) {
EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(frontTask),
- frontTask, null, INVALID_STACK_ID, false));
+ frontTask, null, false));
return true;
}
}
@@ -2369,12 +2369,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void run() {
EventBus.getDefault().send(new LaunchTaskEvent(
getChildViewForTask(task), task, null,
- INVALID_STACK_ID, false /* screenPinningRequested */));
+ false /* screenPinningRequested */));
}
});
} else {
- EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task),
- task, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+ EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task), task, null,
+ false /* screenPinningRequested */));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index ceeebd96a3e1..c64f6dfcea4a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -674,8 +674,7 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
mActionButtonView.setTranslationZ(0f);
screenPinningRequested = true;
}
- EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, INVALID_STACK_ID,
- screenPinningRequested));
+ EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, screenPinningRequested));
MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
mTask.key.getComponent().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index ae922fcc218e..198ecae2d1a9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -16,6 +16,11 @@
package com.android.systemui.recents.views;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
@@ -57,10 +62,6 @@ import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
/* The task bar view */
public class TaskViewHeader extends FrameLayout
implements View.OnClickListener, View.OnLongClickListener {
@@ -172,7 +173,7 @@ public class TaskViewHeader extends FrameLayout
int mTaskBarViewLightTextColor;
int mTaskBarViewDarkTextColor;
int mDisabledTaskBarBackgroundColor;
- int mMoveTaskTargetStackId = INVALID_STACK_ID;
+ int mTaskWindowingMode = WINDOWING_MODE_UNDEFINED;
// Header background
private HighlightColorDrawable mBackground;
@@ -485,12 +486,12 @@ public class TaskViewHeader extends FrameLayout
// current task
if (mMoveTaskButton != null) {
if (t.isFreeformTask()) {
- mMoveTaskTargetStackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ mTaskWindowingMode = WINDOWING_MODE_FULLSCREEN;
mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
? mLightFullscreenIcon
: mDarkFullscreenIcon);
} else {
- mMoveTaskTargetStackId = FREEFORM_WORKSPACE_STACK_ID;
+ mTaskWindowingMode = WINDOWING_MODE_FREEFORM;
mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
? mLightFreeformIcon
: mDarkFreeformIcon);
@@ -621,8 +622,8 @@ public class TaskViewHeader extends FrameLayout
Constants.Metrics.DismissSourceHeaderButton);
} else if (v == mMoveTaskButton) {
TaskView tv = Utilities.findParent(this, TaskView.class);
- EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null,
- mMoveTaskTargetStackId, false));
+ EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null, false,
+ mTaskWindowingMode, ACTIVITY_TYPE_UNDEFINED));
} else if (v == mAppInfoView) {
EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
} else if (v == mAppIconView) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 6bfef20c9f53..44e60eed8c7c 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -93,7 +93,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
- private static final boolean SWAPPING_ENABLED = false;
/**
* How much the background gets scaled when we are in the minimized dock state.
@@ -153,7 +152,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private boolean mEntranceAnimationRunning;
private boolean mExitAnimationRunning;
private int mExitStartPosition;
- private GestureDetector mGestureDetector;
private boolean mDockedStackMinimized;
private boolean mHomeStackResizable;
private boolean mAdjustedForIme;
@@ -295,21 +293,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
landscape ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW));
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
mHandle.setAccessibilityDelegate(mHandleDelegate);
- mGestureDetector = new GestureDetector(mContext, new SimpleOnGestureListener() {
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- if (SWAPPING_ENABLED) {
- updateDockSide();
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (mDockSide != WindowManager.DOCKED_INVALID
- && !ssp.isRecentsActivityVisible()) {
- mWindowManagerProxy.swapTasks();
- return true;
- }
- }
- return false;
- }
- });
}
@Override
@@ -478,7 +461,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
@Override
public boolean onTouch(View v, MotionEvent event) {
convertToScreenCoordinates(event);
- mGestureDetector.onTouchEvent(event);
final int action = event.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
case MotionEvent.ACTION_DOWN:
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index c24512649c2f..185f6e369f76 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -120,17 +120,6 @@ public class WindowManagerProxy {
}
};
- private final Runnable mSwapRunnable = new Runnable() {
- @Override
- public void run() {
- try {
- ActivityManager.getService().swapDockedAndFullscreenStack();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to resize stack: " + e);
- }
- }
- };
-
private final Runnable mSetTouchableRegionRunnable = new Runnable() {
@Override
public void run() {
@@ -218,10 +207,6 @@ public class WindowManagerProxy {
mExecutor.execute(mDimLayerRunnable);
}
- public void swapTasks() {
- mExecutor.execute(mSwapRunnable);
- }
-
public void setTouchRegion(Rect region) {
synchronized (mDockedRect) {
mTouchableRegion.set(region);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index 7e08d5605f40..9d2d71e28e5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -15,6 +15,12 @@
*/
package com.android.systemui.statusbar.car;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.app.ActivityManager.StackId;
import android.content.Context;
import android.content.Intent;
@@ -117,7 +123,8 @@ class CarNavigationBarController {
// Set up the persistent docked task if needed.
if (mPersistentTaskIntent != null && !mStatusBar.hasDockedTask()
&& stackId != StackId.HOME_STACK_ID) {
- mStatusBar.startActivityOnStack(mPersistentTaskIntent, StackId.DOCKED_STACK_ID);
+ mStatusBar.startActivityOnStack(mPersistentTaskIntent,
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
}
}
@@ -375,13 +382,15 @@ class CarNavigationBarController {
// rather than the "preferred/last run" app.
intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, index == mCurrentFacetIndex);
- int stackId = StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+ int windowingMode = WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+ int activityType = ACTIVITY_TYPE_UNDEFINED;
if (intent.getCategories().contains(Intent.CATEGORY_HOME)) {
- stackId = StackId.HOME_STACK_ID;
+ windowingMode = WINDOWING_MODE_UNDEFINED;
+ activityType = ACTIVITY_TYPE_HOME;
}
setCurrentFacet(index);
- mStatusBar.startActivityOnStack(intent, stackId);
+ mStatusBar.startActivityOnStack(intent, windowingMode, activityType);
}
/**
@@ -391,6 +400,7 @@ class CarNavigationBarController {
*/
private void onFacetLongClicked(Intent intent, int index) {
setCurrentFacet(index);
- mStatusBar.startActivityOnStack(intent, StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+ mStatusBar.startActivityOnStack(intent,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_UNDEFINED);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 680f693a83f8..10fc496fcfd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -378,9 +378,10 @@ public class CarStatusBar extends StatusBar implements
return result;
}
- public int startActivityOnStack(Intent intent, int stackId) {
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(stackId);
+ public int startActivityOnStack(Intent intent, int windowingMode, int activityType) {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(windowingMode);
+ options.setLaunchActivityType(activityType);
return startActivityWithOptions(intent, options.toBundle());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 200cada972a7..4739a2eed6de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -20,6 +20,7 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
@@ -37,7 +38,6 @@ import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.INotificationManager;
import android.app.KeyguardManager;
@@ -1057,6 +1057,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationData.setHeadsUpManager(mHeadsUpManager);
mGroupManager.setHeadsUpManager(mHeadsUpManager);
mHeadsUpManager.setVisualStabilityManager(mVisualStabilityManager);
+ putComponent(HeadsUpManager.class, mHeadsUpManager);
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
@@ -5931,7 +5932,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
return super.onClickHandler(view, pendingIntent, fillInIntent,
- StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
}
private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
@@ -7148,10 +7149,10 @@ public class StatusBar extends SystemUI implements DemoMode,
}
protected Bundle getActivityOptions() {
- // Anything launched from the notification shade should always go into the
- // fullscreen stack.
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+ // Anything launched from the notification shade should always go into the secondary
+ // split-screen windowing mode.
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
return options.toBundle();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index bb7b197c2a05..b7e6a40c6880 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -16,11 +16,21 @@
package com.android.systemui.statusbar.policy;
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiManager;
-import android.os.Looper;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.telephony.PhoneStateListener;
@@ -29,16 +39,18 @@ import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.testing.TestableLooper;
import android.util.Log;
+
import com.android.internal.telephony.cdma.EriInfo;
import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.SignalDrawable;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
-import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Rule;
@@ -46,25 +58,12 @@ import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
public class NetworkControllerBaseTest extends SysuiTestCase {
private static final String TAG = "NetworkControllerBaseTest";
protected static final int DEFAULT_LEVEL = 2;
@@ -131,11 +130,12 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
mUserCallback.onUserSetupChanged();
mUserCallback.onDeviceProvisionedChanged();
+ TestableLooper.get(this).processAllMessages();
return null;
}).when(mMockProvisionController).addCallback(any());
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
- mConfig, Looper.getMainLooper(), mCallbackHandler,
+ mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mMockProvisionController);
setupNetworkController();
@@ -176,7 +176,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
NetworkControllerImpl networkControllerNoMobile
= new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
- mConfig, mContext.getMainLooper(), mCallbackHandler,
+ mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
mock(DeviceProvisionedController.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 0313a4374d55..1419e9ad43a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -9,6 +9,9 @@ import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
import com.android.settingslib.net.DataUsageController;
@@ -16,7 +19,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
public class NetworkControllerDataTest extends NetworkControllerBaseTest {
@Test
@@ -126,6 +130,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
mUserCallback.onUserSetupChanged();
+ TestableLooper.get(this).processAllMessages();
// Don't show the X until the device is setup.
verifyDataIndicators(0, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java
index 9ac51b65f382..d2d73470efe7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java
@@ -3,6 +3,8 @@ package com.android.systemui.statusbar.policy;
import android.net.NetworkCapabilities;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -14,7 +16,8 @@ import org.mockito.Mockito;
import static junit.framework.Assert.assertEquals;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
public class NetworkControllerEthernetTest extends NetworkControllerBaseTest {
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index b353f5ab5137..3ad107c22245 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -25,6 +25,8 @@ import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
@@ -46,7 +48,8 @@ import static junit.framework.Assert.assertFalse;
import static org.mockito.Mockito.mock;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index ffd0165195e5..4c18f8d82750 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -7,6 +7,8 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -21,7 +23,8 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
// These match the constants in WifiManager and need to be kept up to date.
private static final int MIN_RSSI = -100;
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index 777468a9e0d2..437da8f3f17a 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -501,8 +501,8 @@ message WakeupStats {
// between [1001, 9999]. See android.os.Process for possible uids.
optional int64 non_application_wakeups = 6;
- // The total number of wakeup packets with no associated sockets.
- optional int64 unrouted_wakeups = 7;
+ // The total number of wakeup packets with no associated socket or uid.
+ optional int64 no_uid_wakeups = 7;
}
// Represents one of the IP connectivity event defined in this file.
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index aa4217cec802..07302706d134 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4451,6 +4451,82 @@ message MetricsEvent {
// OS: O MR
FIELD_SELECTION_SMART_RANGE = 1123;
+ // The value of an autofillable and savable view was reset
+ // Package: Package of app that was autofilled
+ // OS: O MR
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_PREVIOUS_LENGTH: the previous length of the value
+ AUTOFILL_VALUE_RESET = 1124;
+
+ // Tag of AUTOFILL_VALUE_RESET
+ // OS: O MR
+ FIELD_AUTOFILL_PREVIOUS_LENGTH = 1125;
+
+ // An autofill dataset authentification succeeded
+ // Package: Package of app that was autofilled
+ // OS: O MR
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ AUTOFILL_DATASET_AUTHENTICATED = 1126;
+
+ // An autofill service provided an invalid dataset authentification
+ // Package: Package of app that was autofilled
+ // OS: O MR
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ AUTOFILL_INVALID_DATASET_AUTHENTICATION = 1127;
+
+ // An autofill service provided an invalid authentification extra
+ // Package: Package of app that was autofilled
+ // OS: O MR
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ AUTOFILL_INVALID_AUTHENTICATION = 1128;
+
+ // An autofill service used a custom description (using RemoteViews) in the Save affordance
+ // Package: Package of app that is autofilled
+ // OS: O MR
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+ AUTOFILL_SAVE_CUSTOM_DESCRIPTION = 1129;
+
+ // FIELD - Type of save object passed by the service when the Save UI is shown
+ // OS: O MR
+ FIELD_AUTOFILL_SAVE_TYPE = 1130;
+
+ // An autofill service used a custom subtitle (String) in the Save affordance
+ // Package: Package of app that is autofilled
+ // OS: O MR
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+ AUTOFILL_SAVE_CUSTOM_SUBTITLE = 1131;
+
+ // User tapped a link in the custom description of the Save affordance provided by an autofill service
+ // Package: Package of app that is autofilled
+ // OS: O MR
+ // Type TYPE_UNKNOWN: The link was not properly set by the service
+ // Type TYPE_OPEN: The link launched an activity
+ // Type TYPE_FAILURE: The link could not launc an activity
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+ AUTOFILL_SAVE_LINK_TAPPED = 1132;
+
+ // Result of the validation on save when an autofill service provided a validator
+ // Package: Package of app that is autofilled
+ // OS: O MR
+ // Type TYPE_FAILURE: The validation could not be performed due to an error
+ // Type TYPE_SUCCESS: The validation passed
+ // Type TYPE_DISMISS: The validation failed
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+ AUTOFILL_SAVE_VALIDATION = 1133;
+
+ // Result of an operation in the autofill save affordance after the user tapped a link in the custom description
+ // provided by the autofill service
+ // Package: Package of app that is autofilled
+ // OS: O MR
+ // Type TYPE_OPEN: The save affordance was restored
+ // Type TYPE_DISMISS: The save affordcance was destroyed
+ // Type TYPE_FAILURE: An invalid opperation was reported by the app's AutofillManager
+ AUTOFILL_PENDING_SAVE_UI_OPERATION = 1134;
+
// ---- End O-MR1 Constants, all O-MR1 constants go above this line ----
// OPEN: Settings > Network & Internet > Mobile network
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index ddc819d39d5e..a1c75bfc16c0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -650,7 +650,7 @@ public final class AutofillManagerService extends SystemService {
synchronized (mLock) {
final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service == null) return false;
- return Objects.equals(packageName, service.getPackageName());
+ return Objects.equals(packageName, service.getServicePackageName());
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index f2f96f824e5b..7212b2335a47 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -146,8 +146,9 @@ final class AutofillManagerServiceImpl {
updateLocked(disabled);
}
+ @Nullable
CharSequence getServiceName() {
- final String packageName = getPackageName();
+ final String packageName = getServicePackageName();
if (packageName == null) {
return null;
}
@@ -162,7 +163,8 @@ final class AutofillManagerServiceImpl {
}
}
- String getPackageName() {
+ @Nullable
+ String getServicePackageName() {
final ComponentName serviceComponent = getServiceComponentName();
if (serviceComponent != null) {
return serviceComponent.getPackageName();
@@ -636,7 +638,7 @@ final class AutofillManagerServiceImpl {
void destroySessionsLocked() {
if (mSessions.size() == 0) {
- mUi.destroyAll(null, null);
+ mUi.destroyAll(null, null, false);
return;
}
while (mSessions.size() > 0) {
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 086dd29f0c97..236fbfd94f53 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -18,6 +18,7 @@ package com.android.server.autofill;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.metrics.LogMaker;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.util.ArrayMap;
@@ -25,6 +26,8 @@ import android.util.ArraySet;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
@@ -99,4 +102,14 @@ public final class Helper {
}
return fields;
}
+
+ @NonNull
+ public static LogMaker newLogMaker(int category, String packageName,
+ String servicePackageName) {
+ final LogMaker log = new LogMaker(category).setPackageName(packageName);
+ if (servicePackageName != null) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+ }
+ return log;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index f315148547e9..af55807ff1f0 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -578,9 +578,8 @@ final class RemoteFillService implements DeathRecipient {
public void run() {
synchronized (mLock) {
if (isCancelledLocked()) {
- // TODO(b/653742740): we should probably return here, but for now we're justing
- // logging to confirm this is the problem if it happens again.
- Slog.e(LOG_TAG, "run() called after canceled: " + mRequest);
+ if (sDebug) Slog.d(LOG_TAG, "run() called after canceled: " + mRequest);
+ return;
}
}
final RemoteFillService remoteService = getService();
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 171053fd8ddf..ed3441ff7328 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -417,7 +417,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mPackageName = packageName;
mClient = IAutoFillManagerClient.Stub.asInterface(client);
- mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_STARTED, mPackageName);
+ writeLog(MetricsEvent.AUTOFILL_SESSION_STARTED);
}
/**
@@ -471,19 +471,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if ((response.getDatasets() == null || response.getDatasets().isEmpty())
&& response.getAuthentication() == null) {
// Response is "empty" from an UI point of view, need to notify client.
- notifyUnavailableToClient();
+ notifyUnavailableToClient(false);
}
synchronized (mLock) {
processResponseLocked(response, requestFlags);
}
- final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
.setType(MetricsEvent.TYPE_SUCCESS)
- .setPackageName(mPackageName)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
- response.getDatasets() == null ? 0 : response.getDatasets().size())
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE,
- servicePackageName);
+ response.getDatasets() == null ? 0 : response.getDatasets().size());
mMetricsLogger.write(log);
}
@@ -499,10 +496,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
mService.resetLastResponse();
}
- LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
- .setType(MetricsEvent.TYPE_FAILURE)
- .setPackageName(mPackageName)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+ LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
+ .setType(MetricsEvent.TYPE_FAILURE);
mMetricsLogger.write(log);
getUiForShowing().showError(message, this);
@@ -521,11 +516,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
}
- LogMaker log = (new LogMaker(
- MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
- .setType(MetricsEvent.TYPE_SUCCESS)
- .setPackageName(mPackageName)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+ LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
+ .setType(MetricsEvent.TYPE_SUCCESS);
mMetricsLogger.write(log);
// Nothing left to do...
@@ -545,11 +537,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
}
- LogMaker log = (new LogMaker(
- MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
- .setType(MetricsEvent.TYPE_FAILURE)
- .setPackageName(mPackageName)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+ LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
+ .setType(MetricsEvent.TYPE_FAILURE);
mMetricsLogger.write(log);
getUiForShowing().showError(message, this);
@@ -583,6 +572,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// FillServiceCallbacks
@Override
public void authenticate(int requestId, int datasetIndex, IntentSender intent, Bundle extras) {
+ if (sDebug) {
+ Slog.d(TAG, "authenticate(): requestId=" + requestId + "; datasetIdx=" + datasetIndex
+ + "; intentSender=" + intent);
+ }
final Intent fillInIntent;
synchronized (mLock) {
if (mDestroyed) {
@@ -591,6 +584,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
fillInIntent = createAuthFillInIntentLocked(requestId, extras);
+ if (fillInIntent == null) {
+ forceRemoveSelfLocked();
+ return;
+ }
}
mService.setAuthenticationSelected(id, mClientState);
@@ -746,21 +743,22 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (sDebug) Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result);
if (result instanceof FillResponse) {
- final FillResponse response = (FillResponse) result;
- mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
- replaceResponseLocked(authenticatedResponse, response);
+ writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED);
+ replaceResponseLocked(authenticatedResponse, (FillResponse) result);
} else if (result instanceof Dataset) {
- // TODO: add proper metric
if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
+ writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
final Dataset dataset = (Dataset) result;
authenticatedResponse.getDatasets().set(datasetIdx, dataset);
autoFill(requestId, datasetIdx, dataset, false);
+ } else {
+ writeLog(MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
}
} else {
if (result != null) {
Slog.w(TAG, "service returned invalid auth type: " + result);
}
- // TODO: add proper metric (on else)
+ writeLog(MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
processNullResponseLocked(0);
}
}
@@ -774,43 +772,57 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mHasCallback = hasIt;
}
- /**
- * Shows the save UI, when session can be saved.
- *
- * @return {@code true} if session is done, or {@code false} if it's pending user action.
- */
- public boolean showSaveLocked() {
- if (mDestroyed) {
- Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: "
- + id + " destroyed");
- return false;
- }
+ @Nullable
+ private FillResponse getLastResponseLocked(@Nullable String logPrefix) {
if (mContexts == null) {
- Slog.d(TAG, "showSaveLocked(): no contexts");
- return true;
+ if (sDebug && logPrefix != null) Slog.d(TAG, logPrefix + ": no contexts");
+ return null;
}
if (mResponses == null) {
// Happens when the activity / session was finished before the service replied, or
// when the service cannot autofill it (and returned a null response).
- if (sVerbose) {
- Slog.v(TAG, "showSaveLocked(): no responses on session");
+ if (sVerbose && logPrefix != null) {
+ Slog.v(TAG, logPrefix + ": no responses on session");
}
- return true;
+ return null;
}
final int lastResponseIdx = getLastResponseIndexLocked();
if (lastResponseIdx < 0) {
- Slog.w(TAG, "showSaveLocked(): did not get last response. mResponses=" + mResponses
- + ", mViewStates=" + mViewStates);
- return true;
+ if (logPrefix != null) {
+ Slog.w(TAG, logPrefix + ": did not get last response. mResponses=" + mResponses
+ + ", mViewStates=" + mViewStates);
+ }
+ return null;
}
final FillResponse response = mResponses.valueAt(lastResponseIdx);
- final SaveInfo saveInfo = response.getSaveInfo();
- if (sVerbose) {
- Slog.v(TAG, "showSaveLocked(): mResponses=" + mResponses + ", mContexts=" + mContexts
+ if (sVerbose && logPrefix != null) {
+ Slog.v(TAG, logPrefix + ": mResponses=" + mResponses + ", mContexts=" + mContexts
+ ", mViewStates=" + mViewStates);
}
+ return response;
+ }
+
+ @Nullable
+ private SaveInfo getSaveInfoLocked() {
+ final FillResponse response = getLastResponseLocked(null);
+ return response == null ? null : response.getSaveInfo();
+ }
+
+ /**
+ * Shows the save UI, when session can be saved.
+ *
+ * @return {@code true} if session is done, or {@code false} if it's pending user action.
+ */
+ public boolean showSaveLocked() {
+ if (mDestroyed) {
+ Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: "
+ + id + " destroyed");
+ return false;
+ }
+ final FillResponse response = getLastResponseLocked("showSaveLocked()");
+ final SaveInfo saveInfo = response == null ? null : response.getSaveInfo();
/*
* The Save dialog is only shown if all conditions below are met:
@@ -922,15 +934,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final InternalValidator validator = saveInfo.getValidator();
if (validator != null) {
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_VALIDATION);
boolean isValid;
try {
isValid = validator.isValid(valueFinder);
+ log.setType(isValid
+ ? MetricsEvent.TYPE_SUCCESS
+ : MetricsEvent.TYPE_DISMISS);
} catch (Exception e) {
- Slog.e(TAG, "Not showing save UI because of exception during validation "
- + e.getClass());
+ Slog.e(TAG, "Not showing save UI because validation failed:", e);
+ log.setType(MetricsEvent.TYPE_FAILURE);
+ mMetricsLogger.write(log);
return true;
}
+ mMetricsLogger.write(log);
if (!isValid) {
Slog.i(TAG, "not showing save UI because fields failed validation");
return true;
@@ -978,7 +996,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final IAutoFillManagerClient client = getClient();
mPendingSaveUi = new PendingUi(mActivityToken, id, client);
getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
- saveInfo, valueFinder, mPackageName, this, mPendingSaveUi);
+ mService.getServicePackageName(), saveInfo, valueFinder, mPackageName, this,
+ mPendingSaveUi);
if (client != null) {
try {
client.setSaveUiState(id, true);
@@ -1244,6 +1263,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
break;
case ACTION_VALUE_CHANGED:
if (value != null && !value.equals(viewState.getCurrentValue())) {
+ if (value.isEmpty()
+ && viewState.getCurrentValue() != null
+ && viewState.getCurrentValue().isText()
+ && viewState.getCurrentValue().getTextValue() != null
+ && getSaveInfoLocked() != null) {
+ final int length = viewState.getCurrentValue().getTextValue().length();
+ if (sDebug) {
+ Slog.d(TAG, "updateLocked(" + id + "): resetting value that was "
+ + length + " chars long");
+ }
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_VALUE_RESET)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_PREVIOUS_LENGTH, length);
+ mMetricsLogger.write(log);
+ }
+
// Always update the internal state.
viewState.setCurrentValue(value);
@@ -1319,7 +1353,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
filterText = value.getTextValue().toString();
}
- getUiForShowing().showFillUi(filledId, response, filterText, mPackageName, this);
+ getUiForShowing().showFillUi(filledId, response, filterText,
+ mService.getServicePackageName(), mPackageName, this);
}
boolean isDestroyed() {
@@ -1334,11 +1369,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
- private void notifyUnavailableToClient() {
+ private void notifyUnavailableToClient(boolean sessionFinished) {
synchronized (mLock) {
- if (!mHasCallback || mCurrentViewId == null) return;
+ if (mCurrentViewId == null) return;
try {
- mClient.notifyNoFillUi(id, mCurrentViewId);
+ if (mHasCallback) {
+ mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinished);
+ } else if (sessionFinished) {
+ mClient.setSessionFinished();
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e);
}
@@ -1426,7 +1465,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
mService.resetLastResponse();
// Nothing to be done, but need to notify client.
- notifyUnavailableToClient();
+ notifyUnavailableToClient(true);
removeSelf();
}
@@ -1545,6 +1584,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
void autoFill(int requestId, int datasetIndex, Dataset dataset, boolean generateEvent) {
+ if (sDebug) {
+ Slog.d(TAG, "autoFill(): requestId=" + requestId + "; datasetIdx=" + datasetIndex
+ + "; dataset=" + dataset);
+ }
synchronized (mLock) {
if (mDestroyed) {
Slog.w(TAG, "Call to Session#autoFill() rejected - session: "
@@ -1565,10 +1608,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mService.logDatasetAuthenticationSelected(dataset.getId(), id, mClientState);
setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
final Intent fillInIntent = createAuthFillInIntentLocked(requestId, mClientState);
-
+ if (fillInIntent == null) {
+ forceRemoveSelfLocked();
+ return;
+ }
final int authenticationId = AutofillManager.makeAuthenticationId(requestId,
datasetIndex);
startAuthentication(authenticationId, dataset.getAuthentication(), fillInIntent);
+
}
}
@@ -1578,14 +1625,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
+ // TODO: this should never be null, but we got at least one occurrence, probably due to a race.
+ @Nullable
private Intent createAuthFillInIntentLocked(int requestId, Bundle extras) {
final Intent fillInIntent = new Intent();
final FillContext context = getFillContextByRequestIdLocked(requestId);
if (context == null) {
- // TODO(b/653742740): this will crash system_server. We need to handle it, but we're
- // keeping it crashing for now so we can diagnose when it happens again
- Slog.wtf(TAG, "no FillContext for requestId" + requestId + "; mContexts= " + mContexts);
+ Slog.wtf(TAG, "createAuthFillInIntentLocked(): no FillContext. requestId=" + requestId
+ + "; mContexts= " + mContexts);
+ return null;
}
fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, context.getStructure());
fillInIntent.putExtra(AutofillManager.EXTRA_CLIENT_STATE, extras);
@@ -1732,10 +1781,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (mDestroyed) {
return null;
}
- mUi.destroyAll(mPendingSaveUi, this);
+ mUi.destroyAll(mPendingSaveUi, this, true);
mUi.clearCallback(this);
mDestroyed = true;
- mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName);
+ writeLog(MetricsEvent.AUTOFILL_SESSION_FINISHED);
return mRemoteFillService;
}
@@ -1748,7 +1797,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mPendingSaveUi = null;
removeSelfLocked();
- mUi.destroyAll(mPendingSaveUi, this);
+
+ mHandlerCaller.getHandler().post(() -> {
+ try {
+ mClient.setState(mService.isEnabled(), true, false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "error updating client state: " + e);
+ }
+ });
+
+ mUi.destroyAll(mPendingSaveUi, this, false);
}
/**
@@ -1820,4 +1878,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
return lastResponseIdx;
}
+
+ private LogMaker newLogMaker(int category) {
+ return newLogMaker(category, mService.getServicePackageName());
+ }
+
+ private LogMaker newLogMaker(int category, String servicePackageName) {
+ return Helper.newLogMaker(category, mPackageName, servicePackageName);
+ }
+
+ private void writeLog(int category) {
+ mMetricsLogger.write(newLogMaker(category));
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index cac2bff579ed..36b95fc02ed8 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -40,8 +40,9 @@ import android.view.autofill.IAutofillWindowPresenter;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.UiThread;
+import com.android.server.autofill.Helper;
import java.io.PrintWriter;
@@ -158,21 +159,22 @@ public final class AutoFillUI {
* @param focusedId the currently focused field
* @param response the current fill response
* @param filterText text of the view to be filled
+ * @param servicePackageName package name of the autofill service filling the activity
* @param packageName package name of the activity that is filled
* @param callback Identifier for the caller
*/
public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
- @Nullable String filterText, @NonNull String packageName,
- @NonNull AutoFillUiCallback callback) {
+ @Nullable String filterText, @Nullable String servicePackageName,
+ @NonNull String packageName, @NonNull AutoFillUiCallback callback) {
if (sDebug) {
final int size = filterText == null ? 0 : filterText.length();
Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars");
}
- final LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_FILL_UI))
- .setPackageName(packageName)
- .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
+ final LogMaker log =
+ Helper.newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, packageName, servicePackageName)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
filterText == null ? 0 : filterText.length())
- .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
response.getDatasets() == null ? 0 : response.getDatasets().size());
mHandler.post(() -> {
@@ -184,7 +186,7 @@ public final class AutoFillUI {
filterText, mOverlayControl, new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
- log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
+ log.setType(MetricsEvent.TYPE_DETAIL);
hideFillUiUiThread(callback);
if (mCallback != null) {
mCallback.authenticate(response.getRequestId(),
@@ -195,7 +197,7 @@ public final class AutoFillUI {
@Override
public void onDatasetPicked(Dataset dataset) {
- log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+ log.setType(MetricsEvent.TYPE_ACTION);
hideFillUiUiThread(callback);
if (mCallback != null) {
final int datasetIndex = response.getDatasets().indexOf(dataset);
@@ -205,14 +207,14 @@ public final class AutoFillUI {
@Override
public void onCanceled() {
- log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
+ log.setType(MetricsEvent.TYPE_DISMISS);
hideFillUiUiThread(callback);
}
@Override
public void onDestroy() {
- if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
- log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+ if (log.getType() == MetricsEvent.TYPE_UNKNOWN) {
+ log.setType(MetricsEvent.TYPE_CLOSE);
}
mMetricsLogger.write(log);
}
@@ -246,37 +248,39 @@ public final class AutoFillUI {
* Shows the UI asking the user to save for autofill.
*/
public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
- @NonNull SaveInfo info,@NonNull ValueFinder valueFinder, @NonNull String packageName,
+ @Nullable String servicePackageName, @NonNull SaveInfo info,
+ @NonNull ValueFinder valueFinder, @NonNull String packageName,
@NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi) {
if (sVerbose) Slog.v(TAG, "showSaveUi() for " + packageName + ": " + info);
int numIds = 0;
numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length;
- LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_SAVE_UI))
- .setPackageName(packageName).addTaggedData(
- MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
+ final LogMaker log =
+ Helper.newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, packageName, servicePackageName)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
mHandler.post(() -> {
if (callback != mCallback) {
return;
}
hideAllUiThread(callback);
- mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon, info,
- valueFinder, mOverlayControl, new SaveUi.OnSaveListener() {
+ mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon,
+ servicePackageName, packageName, info, valueFinder, mOverlayControl,
+ new SaveUi.OnSaveListener() {
@Override
public void onSave() {
- log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+ log.setType(MetricsEvent.TYPE_ACTION);
hideSaveUiUiThread(mCallback);
if (mCallback != null) {
mCallback.save();
}
- destroySaveUiUiThread(pendingSaveUi);
+ destroySaveUiUiThread(pendingSaveUi, true);
}
@Override
public void onCancel(IntentSender listener) {
- log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
+ log.setType(MetricsEvent.TYPE_DISMISS);
hideSaveUiUiThread(mCallback);
if (listener != null) {
try {
@@ -289,13 +293,13 @@ public final class AutoFillUI {
if (mCallback != null) {
mCallback.cancelSave();
}
- destroySaveUiUiThread(pendingSaveUi);
+ destroySaveUiUiThread(pendingSaveUi, true);
}
@Override
public void onDestroy() {
- if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
- log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+ if (log.getType() == MetricsEvent.TYPE_UNKNOWN) {
+ log.setType(MetricsEvent.TYPE_CLOSE);
if (mCallback != null) {
mCallback.cancelSave();
@@ -331,8 +335,8 @@ public final class AutoFillUI {
* Destroy all UI affordances.
*/
public void destroyAll(@Nullable PendingUi pendingSaveUi,
- @Nullable AutoFillUiCallback callback) {
- mHandler.post(() -> destroyAllUiThread(pendingSaveUi, callback));
+ @Nullable AutoFillUiCallback callback, boolean notifyClient) {
+ mHandler.post(() -> destroyAllUiThread(pendingSaveUi, callback, notifyClient));
}
public void dump(PrintWriter pw) {
@@ -375,7 +379,7 @@ public final class AutoFillUI {
}
@android.annotation.UiThread
- private void destroySaveUiUiThread(@Nullable PendingUi pendingSaveUi) {
+ private void destroySaveUiUiThread(@Nullable PendingUi pendingSaveUi, boolean notifyClient) {
if (mSaveUi == null) {
// Calling destroySaveUiUiThread() twice is normal - it usually happens when the
// first call is made after the SaveUI is hidden and the second when the session is
@@ -387,7 +391,7 @@ public final class AutoFillUI {
if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): " + pendingSaveUi);
mSaveUi.destroy();
mSaveUi = null;
- if (pendingSaveUi != null) {
+ if (pendingSaveUi != null && notifyClient) {
try {
if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): notifying client");
pendingSaveUi.client.setSaveUiState(pendingSaveUi.id, false);
@@ -399,9 +403,9 @@ public final class AutoFillUI {
@android.annotation.UiThread
private void destroyAllUiThread(@Nullable PendingUi pendingSaveUi,
- @Nullable AutoFillUiCallback callback) {
+ @Nullable AutoFillUiCallback callback, boolean notifyClient) {
hideFillUiUiThread(callback);
- destroySaveUiUiThread(pendingSaveUi);
+ destroySaveUiUiThread(pendingSaveUi, notifyClient);
}
@android.annotation.UiThread
@@ -413,7 +417,7 @@ public final class AutoFillUI {
Slog.d(TAG, "hideAllUiThread(): "
+ "destroying Save UI because pending restoration is finished");
}
- destroySaveUiUiThread(pendingSaveUi);
+ destroySaveUiUiThread(pendingSaveUi, true);
}
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index d0b2e9240b58..32f4d69fc3e3 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -20,16 +20,15 @@ import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -53,6 +52,8 @@ import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.R;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.UiThread;
import java.io.PrintWriter;
@@ -111,6 +112,7 @@ final class SaveUi {
}
private final Handler mHandler = UiThread.getHandler();
+ private final MetricsLogger mMetricsLogger = new MetricsLogger();
private final @NonNull Dialog mDialog;
@@ -121,16 +123,21 @@ final class SaveUi {
private final CharSequence mTitle;
private final CharSequence mSubTitle;
private final PendingUi mPendingUi;
+ private final String mServicePackageName;
+ private final String mPackageName;
private boolean mDestroyed;
SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
+ @Nullable String servicePackageName, @NonNull String packageName,
@NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
@NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener) {
mPendingUi= pendingUi;
mListener = new OneTimeListener(listener);
mOverlayControl = overlayControl;
+ mServicePackageName = servicePackageName;
+ mPackageName = packageName;
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
@@ -181,6 +188,8 @@ final class SaveUi {
ScrollView subtitleContainer = null;
final CustomDescription customDescription = info.getCustomDescription();
if (customDescription != null) {
+ writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION, type);
+
mSubTitle = null;
if (sDebug) Slog.d(TAG, "Using custom description");
@@ -190,40 +199,35 @@ final class SaveUi {
@Override
public boolean onClickHandler(View view, PendingIntent pendingIntent,
Intent intent) {
+ final LogMaker log =
+ newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, type);
// We need to hide the Save UI before launching the pending intent, and
// restore back it once the activity is finished, and that's achieved by
// adding a custom extra in the activity intent.
- if (pendingIntent != null) {
- if (intent == null) {
- Slog.w(TAG,
- "remote view on custom description does not have intent");
- return false;
- }
- if (!pendingIntent.isActivity()) {
- Slog.w(TAG, "ignoring custom description pending intent that's not "
- + "for an activity: " + pendingIntent);
- return false;
- }
- if (sVerbose) {
- Slog.v(TAG,
- "Intercepting custom description intent: " + intent);
- }
- final IBinder token = mPendingUi.getToken();
- intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
- try {
- pendingUi.client.startIntentSender(pendingIntent.getIntentSender(),
- intent);
- mPendingUi.setState(PendingUi.STATE_PENDING);
- if (sDebug) {
- Slog.d(TAG, "hiding UI until restored with token " + token);
- }
- hide();
- } catch (RemoteException e) {
- Slog.w(TAG, "error triggering pending intent: " + intent);
- return false;
- }
+ final boolean isValid = isValidLink(pendingIntent, intent);
+ if (!isValid) {
+ log.setType(MetricsEvent.TYPE_UNKNOWN);
+ mMetricsLogger.write(log);
+ return false;
+ }
+ if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
+ final IBinder token = mPendingUi.getToken();
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
+ try {
+ pendingUi.client.startIntentSender(pendingIntent.getIntentSender(),
+ intent);
+ mPendingUi.setState(PendingUi.STATE_PENDING);
+ if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token);
+ hide();
+ log.setType(MetricsEvent.TYPE_OPEN);
+ mMetricsLogger.write(log);
+ return true;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "error triggering pending intent: " + intent);
+ log.setType(MetricsEvent.TYPE_FAILURE);
+ mMetricsLogger.write(log);
+ return false;
}
- return true;
}
};
@@ -241,6 +245,7 @@ final class SaveUi {
} else {
mSubTitle = info.getDescription();
if (mSubTitle != null) {
+ writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type);
subtitleContainer = view.findViewById(R.id.autofill_save_custom_subtitle);
final TextView subtitleView = new TextView(context);
subtitleView.setText(mSubTitle);
@@ -309,8 +314,39 @@ final class SaveUi {
Slog.w(TAG, "Not adding service icon of size "
+ "(" + actualWidth + "x" + actualHeight + ") because maximum is "
+ "(" + maxWidth + "x" + maxHeight + ").");
- iconView.setVisibility(View.INVISIBLE);
+ ((ViewGroup)iconView.getParent()).removeView(iconView);
+ }
+ }
+
+ private static boolean isValidLink(PendingIntent pendingIntent, Intent intent) {
+ if (pendingIntent == null) {
+ Slog.w(TAG, "isValidLink(): custom description without pending intent");
+ return false;
}
+ if (!pendingIntent.isActivity()) {
+ Slog.w(TAG, "isValidLink(): pending intent not for activity");
+ return false;
+ }
+ if (intent == null) {
+ Slog.w(TAG, "isValidLink(): no intent");
+ return false;
+ }
+ return true;
+ }
+
+ private LogMaker newLogMaker(int category, int saveType) {
+ return newLogMaker(category)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SAVE_TYPE, saveType);
+ }
+
+ private LogMaker newLogMaker(int category) {
+ return new LogMaker(category)
+ .setPackageName(mPackageName)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, mServicePackageName);
+ }
+
+ private void writeLog(int category, int saveType) {
+ mMetricsLogger.write(newLogMaker(category, saveType));
}
/**
@@ -326,17 +362,25 @@ final class SaveUi {
+ mPendingUi.getToken());
return;
}
- switch (operation) {
- case AutofillManager.PENDING_UI_OPERATION_RESTORE:
- if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token);
- show();
- break;
- case AutofillManager.PENDING_UI_OPERATION_CANCEL:
- if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token);
- hide();
- break;
- default:
- Slog.w(TAG, "restore(): invalid operation " + operation);
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_PENDING_SAVE_UI_OPERATION);
+ try {
+ switch (operation) {
+ case AutofillManager.PENDING_UI_OPERATION_RESTORE:
+ if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token);
+ log.setType(MetricsEvent.TYPE_OPEN);
+ show();
+ break;
+ case AutofillManager.PENDING_UI_OPERATION_CANCEL:
+ log.setType(MetricsEvent.TYPE_DISMISS);
+ if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token);
+ hide();
+ break;
+ default:
+ log.setType(MetricsEvent.TYPE_FAILURE);
+ Slog.w(TAG, "restore(): invalid operation " + operation);
+ }
+ } finally {
+ mMetricsLogger.write(log);
}
mPendingUi.setState(PendingUi.STATE_FINISHED);
}
@@ -385,6 +429,8 @@ final class SaveUi {
pw.print(prefix); pw.print("title: "); pw.println(mTitle);
pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
pw.print(prefix); pw.print("pendingUi: "); pw.println(mPendingUi);
+ pw.print(prefix); pw.print("service: "); pw.println(mServicePackageName);
+ pw.print(prefix); pw.print("app: "); pw.println(mPackageName);
final View view = mDialog.getWindow().getDecorView();
final int[] loc = view.getLocationOnScreen();
diff --git a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
index 187d5d93bfdd..e29b7d58e018 100644
--- a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
+++ b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
@@ -21,7 +21,10 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.backup.RefactoredBackupManagerService;
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
import java.io.EOFException;
+import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
@@ -130,7 +133,8 @@ final class ProcessedPackagesJournal {
return;
}
- try (RandomAccessFile oldJournal = new RandomAccessFile(journalFile, "r")) {
+ try (DataInputStream oldJournal = new DataInputStream(
+ new BufferedInputStream(new FileInputStream(journalFile)))) {
while (true) {
String packageName = oldJournal.readUTF();
if (DEBUG) {
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 1dede4713ab8..8b4cc7f6d22b 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -679,6 +679,29 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
return token;
}
+ /*
+ * Construct a backup agent instance for the metadata pseudopackage. This is a
+ * process-local non-lifecycle agent instance, so we manually set up the context
+ * topology for it.
+ */
+ public PackageManagerBackupAgent makeMetadataAgent() {
+ PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager);
+ pmAgent.attach(mContext);
+ pmAgent.onCreate();
+ return pmAgent;
+ }
+
+ /*
+ * Same as above but with the explicit package-set configuration.
+ */
+ public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) {
+ PackageManagerBackupAgent pmAgent =
+ new PackageManagerBackupAgent(mPackageManager, packages);
+ pmAgent.attach(mContext);
+ pmAgent.onCreate();
+ return pmAgent;
+ }
+
// ----- Debug-only backup operation trace -----
public void addBackupTrace(String s) {
if (DEBUG_BACKUP_TRACE) {
@@ -809,17 +832,18 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
// Remember our ancestral dataset
mTokenFile = new File(mBaseStateDir, "ancestral");
- try (RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r")) {
- int version = tf.readInt();
+ try (DataInputStream tokenStream = new DataInputStream(new BufferedInputStream(
+ new FileInputStream(mTokenFile)))) {
+ int version = tokenStream.readInt();
if (version == CURRENT_ANCESTRAL_RECORD_VERSION) {
- mAncestralToken = tf.readLong();
- mCurrentToken = tf.readLong();
+ mAncestralToken = tokenStream.readLong();
+ mCurrentToken = tokenStream.readLong();
- int numPackages = tf.readInt();
+ int numPackages = tokenStream.readInt();
if (numPackages >= 0) {
mAncestralPackages = new HashSet<>();
for (int i = 0; i < numPackages; i++) {
- String pkgName = tf.readUTF();
+ String pkgName = tokenStream.readUTF();
mAncestralPackages.add(pkgName);
}
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index edb65a42035f..90134e1a3ead 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -306,6 +306,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
final int N = mPackages.size();
final byte[] buffer = new byte[8192];
for (int i = 0; i < N; i++) {
+ mBackupRunner = null;
PackageInfo currentPackage = mPackages.get(i);
String packageName = currentPackage.packageName;
if (DEBUG) {
@@ -491,7 +492,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
EventLog.writeEvent(EventLogTags.FULL_BACKUP_AGENT_FAILURE, packageName,
"transport rejected");
- // Do nothing, clean up, and continue looping.
+ // This failure state can come either a-priori from the transport, or
+ // from the preflight pass. If we got as far as preflight, we now need
+ // to tear down the target process.
+ if (mBackupRunner != null) {
+ backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+ }
+ // ... and continue looping.
} else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
BackupObserverUtils
.sendBackupOnPackageResult(mBackupObserver, packageName,
@@ -501,6 +508,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED,
packageName);
}
+ backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus == BackupTransport.AGENT_ERROR) {
BackupObserverUtils
@@ -527,6 +535,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE);
// Abort entire backup pass.
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
+ backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
return;
} else {
// Success!
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index 93277d460da4..7a8a920e7df7 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -321,8 +321,7 @@ public class PerformBackupTask implements BackupRestoreTask {
// because it's cheap and this way we guarantee that we don't get out of
// step even if we're selecting among various transports at run time.
if (mStatus == BackupTransport.TRANSPORT_OK) {
- PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
- backupManagerService.getPackageManager());
+ PackageManagerBackupAgent pmAgent = backupManagerService.makeMetadataAgent();
mStatus = invokeAgentForBackup(
PACKAGE_MANAGER_SENTINEL,
IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 62ae065be1ac..22691bb60bfa 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -150,8 +150,7 @@ public class PerformAdbRestoreTask implements Runnable {
mObserver = observer;
mLatchObject = latch;
mAgent = null;
- mPackageManagerBackupAgent = new PackageManagerBackupAgent(
- backupManagerService.getPackageManager());
+ mPackageManagerBackupAgent = backupManagerService.makeMetadataAgent();
mAgentPackage = null;
mTargetApp = null;
mObbConnection = new FullBackupObbConnection(backupManagerService);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 4c0bb48792ae..b538c6d4e472 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -386,8 +386,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// Pull the Package Manager metadata from the restore set first
mCurrentPackage = new PackageInfo();
mCurrentPackage.packageName = PACKAGE_MANAGER_SENTINEL;
- mPmAgent = new PackageManagerBackupAgent(backupManagerService.getPackageManager(),
- null);
+ mPmAgent = backupManagerService.makeMetadataAgent(null);
mAgent = IBackupAgent.Stub.asInterface(mPmAgent.onBind());
if (MORE_DEBUG) {
Slog.v(TAG, "initiating restore for PMBA");
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 86877bab961d..d7cac7770cc8 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -61,6 +61,11 @@ public class AppBackupUtils {
return false;
}
+ // 4. it is an "instant" app
+ if (app.isInstantApp()) {
+ return false;
+ }
+
// Everything else checks out; the only remaining roadblock would be if the
// package were disabled
return !appIsDisabled(app, pm);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index c0fcfd07a75f..c7e22be1972d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -111,8 +111,6 @@ import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
-import com.android.server.NativeDaemonConnector.Command;
-import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.pm.PackageManagerService;
import com.android.server.storage.AppFuseBridge;
@@ -138,7 +136,6 @@ import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -161,8 +158,7 @@ import javax.crypto.spec.PBEKeySpec;
* watch for and manage dynamically added storage, such as SD cards and USB mass
* storage. Also decides how storage should be presented to users on the device.
*/
-class StorageManagerService extends IStorageManager.Stub
- implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {
+class StorageManagerService extends IStorageManager.Stub implements Watchdog.Monitor {
// Static direct instance pointer for the tightly-coupled idle service to use
static StorageManagerService sSelf = null;
@@ -206,18 +202,12 @@ class StorageManagerService extends IStorageManager.Stub
}
}
- /** Flag to enable binder-based interface to vold */
- private static final boolean ENABLE_BINDER = true;
-
private static final boolean DEBUG_EVENTS = false;
private static final boolean DEBUG_OBB = false;
// Disable this since it messes up long-running cryptfs operations.
private static final boolean WATCHDOG_ENABLE = false;
- /** Flag to enable ASECs */
- private static final boolean ASEC_ENABLE = false;
-
/**
* Our goal is for all Android devices to be usable as development devices,
* which includes the new Direct Boot mode added in N. For devices that
@@ -232,66 +222,9 @@ class StorageManagerService extends IStorageManager.Stub
private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
private static final String TAG_STORAGE_TRIM = "storage_trim";
- private static final String VOLD_TAG = "VoldConnector";
- private static final String CRYPTD_TAG = "CryptdConnector";
-
- /** Maximum number of ASEC containers allowed to be mounted. */
- private static final int MAX_CONTAINERS = 250;
-
/** Magic value sent by MoveTask.cpp */
private static final int MOVE_STATUS_COPY_FINISHED = 82;
- /*
- * Internal vold response code constants
- */
- class VoldResponseCode {
- /*
- * 100 series - Requestion action was initiated; expect another reply
- * before proceeding with a new command.
- */
- public static final int VolumeListResult = 110;
- public static final int AsecListResult = 111;
- public static final int StorageUsersListResult = 112;
- public static final int CryptfsGetfieldResult = 113;
-
- /*
- * 200 series - Requestion action has been successfully completed.
- */
- public static final int ShareStatusResult = 210;
- public static final int AsecPathResult = 211;
- public static final int ShareEnabledResult = 212;
-
- /*
- * 400 series - Command was accepted, but the requested action
- * did not take place.
- */
- public static final int OpFailedNoMedia = 401;
- public static final int OpFailedMediaBlank = 402;
- public static final int OpFailedMediaCorrupt = 403;
- public static final int OpFailedVolNotMounted = 404;
- public static final int OpFailedStorageBusy = 405;
- public static final int OpFailedStorageNotFound = 406;
-
- /*
- * 600 series - Unsolicited broadcasts.
- */
- public static final int DISK_CREATED = 640;
- public static final int DISK_SIZE_CHANGED = 641;
- public static final int DISK_LABEL_CHANGED = 642;
- public static final int DISK_SCANNED = 643;
- public static final int DISK_SYS_PATH_CHANGED = 644;
- public static final int DISK_DESTROYED = 649;
-
- public static final int VOLUME_CREATED = 650;
- public static final int VOLUME_STATE_CHANGED = 651;
- public static final int VOLUME_FS_TYPE_CHANGED = 652;
- public static final int VOLUME_FS_UUID_CHANGED = 653;
- public static final int VOLUME_FS_LABEL_CHANGED = 654;
- public static final int VOLUME_PATH_CHANGED = 655;
- public static final int VOLUME_INTERNAL_PATH_CHANGED = 656;
- public static final int VOLUME_DESTROYED = 659;
- }
-
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_PRIMARY = 2;
private static final int VERSION_FIX_PRIMARY = 3;
@@ -472,12 +405,6 @@ class StorageManagerService extends IStorageManager.Stub
private final Context mContext;
- private final NativeDaemonConnector mConnector;
- private final NativeDaemonConnector mCryptConnector;
-
- private final Thread mConnectorThread;
- private final Thread mCryptConnectorThread;
-
private volatile IVold mVold;
private volatile boolean mSystemReady = false;
@@ -489,21 +416,11 @@ class StorageManagerService extends IStorageManager.Stub
private final Callbacks mCallbacks;
private final LockPatternUtils mLockPatternUtils;
- // Two connectors - mConnector & mCryptConnector
- private final CountDownLatch mConnectedSignal = new CountDownLatch(2);
- private final CountDownLatch mAsecsScanned = new CountDownLatch(1);
-
private final Object mUnmountLock = new Object();
@GuardedBy("mUnmountLock")
private CountDownLatch mUnmountSignal;
/**
- * Private hash of currently mounted secure containers.
- * Used as a lock in methods to manipulate secure containers.
- */
- final private HashSet<String> mAsecMountSet = new HashSet<String>();
-
- /**
* The size of the crypto algorithm key in bits for OBB files. Currently
* Twofish is used which takes 128-bit keys.
*/
@@ -616,7 +533,7 @@ class StorageManagerService extends IStorageManager.Stub
if (DEBUG_OBB)
Slog.i(TAG, "onServiceDisconnected");
}
- };
+ }
// Used in the ObbActionHandler
private IMediaContainerService mContainerService = null;
@@ -655,13 +572,6 @@ class StorageManagerService extends IStorageManager.Stub
break;
}
case H_FSTRIM: {
- if (!isReady()) {
- Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again");
- sendMessageDelayed(obtainMessage(H_FSTRIM, msg.obj),
- DateUtils.SECOND_IN_MILLIS);
- break;
- }
-
Slog.i(TAG, "Running fstrim idle maintenance");
// Remember when we kicked it off
@@ -687,12 +597,8 @@ class StorageManagerService extends IStorageManager.Stub
final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
boolean success = false;
try {
- if (ENABLE_BINDER) {
- mVold.shutdown();
- success = true;
- } else {
- success = mConnector.execute("volume", "shutdown").isClassOk();
- }
+ mVold.shutdown();
+ success = true;
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -711,12 +617,7 @@ class StorageManagerService extends IStorageManager.Stub
break;
}
try {
- if (ENABLE_BINDER) {
- mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
- } else {
- mConnector.execute("volume", "mount", vol.id, vol.mountFlags,
- vol.mountUserId);
- }
+ mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -778,11 +679,7 @@ class StorageManagerService extends IStorageManager.Stub
if (Intent.ACTION_USER_ADDED.equals(action)) {
final UserManager um = mContext.getSystemService(UserManager.class);
final int userSerialNumber = um.getUserSerialNumber(userId);
- if (ENABLE_BINDER) {
- mVold.onUserAdded(userId, userSerialNumber);
- } else {
- mConnector.execute("volume", "user_added", userId, userSerialNumber);
- }
+ mVold.onUserAdded(userId, userSerialNumber);
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
synchronized (mVolumes) {
final int size = mVolumes.size();
@@ -794,11 +691,7 @@ class StorageManagerService extends IStorageManager.Stub
}
}
}
- if (ENABLE_BINDER) {
- mVold.onUserRemoved(userId);
- } else {
- mConnector.execute("volume", "user_removed", userId);
- }
+ mVold.onUserRemoved(userId);
}
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -808,11 +701,7 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void waitForAsecScan() {
- waitForLatch(mAsecsScanned, "mAsecsScanned");
- }
-
- private void waitForReady() {
- waitForLatch(mConnectedSignal, "mConnectedSignal");
+ throw new UnsupportedOperationException();
}
private void waitForLatch(CountDownLatch latch, String condition) {
@@ -843,14 +732,6 @@ class StorageManagerService extends IStorageManager.Stub
}
}
- private boolean isReady() {
- try {
- return mConnectedSignal.await(0, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
private void handleSystemReady() {
initIfReadyAndConnected();
resetIfReadyAndConnected();
@@ -917,19 +798,10 @@ class StorageManagerService extends IStorageManager.Stub
for (UserInfo user : users) {
try {
if (initLocked) {
- if (ENABLE_BINDER) {
- mVold.lockUserKey(user.id);
- } else {
- mCryptConnector.execute("cryptfs", "lock_user_key", user.id);
- }
+ mVold.lockUserKey(user.id);
} else {
- if (ENABLE_BINDER) {
- mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
- encodeBytes(null));
- } else {
- mCryptConnector.execute("cryptfs", "unlock_user_key", user.id,
- user.serialNumber, "!", "!");
- }
+ mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
+ encodeBytes(null));
}
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -956,26 +828,14 @@ class StorageManagerService extends IStorageManager.Stub
}
try {
- if (ENABLE_BINDER) {
- mVold.reset();
- } else {
- mConnector.execute("volume", "reset");
- }
+ mVold.reset();
// Tell vold about all existing and started users
for (UserInfo user : users) {
- if (ENABLE_BINDER) {
- mVold.onUserAdded(user.id, user.serialNumber);
- } else {
- mConnector.execute("volume", "user_added", user.id, user.serialNumber);
- }
+ mVold.onUserAdded(user.id, user.serialNumber);
}
for (int userId : systemUnlockedUsers) {
- if (ENABLE_BINDER) {
- mVold.onUserStarted(userId);
- } else {
- mConnector.execute("volume", "user_started", userId);
- }
+ mVold.onUserStarted(userId);
}
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -990,11 +850,7 @@ class StorageManagerService extends IStorageManager.Stub
// staging area is ready so it's ready for zygote-forked apps to
// bind mount against.
try {
- if (ENABLE_BINDER) {
- mVold.onUserStarted(userId);
- } else {
- mConnector.execute("volume", "user_started", userId);
- }
+ mVold.onUserStarted(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -1020,11 +876,7 @@ class StorageManagerService extends IStorageManager.Stub
Slog.d(TAG, "onCleanupUser " + userId);
try {
- if (ENABLE_BINDER) {
- mVold.onUserStopped(userId);
- } else {
- mConnector.execute("volume", "user_stopped", userId);
- }
+ mVold.onUserStopped(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -1050,10 +902,6 @@ class StorageManagerService extends IStorageManager.Stub
return mLastMaintenance;
}
- /**
- * Callback from NativeDaemonConnector
- */
- @Override
public void onDaemonConnected() {
mDaemonConnected = true;
mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
@@ -1063,29 +911,11 @@ class StorageManagerService extends IStorageManager.Stub
initIfReadyAndConnected();
resetIfReadyAndConnected();
- /*
- * Now that we've done our initialization, release
- * the hounds!
- */
- mConnectedSignal.countDown();
- if (mConnectedSignal.getCount() != 0) {
- // More daemons need to connect
- return;
- }
-
// On an encrypted device we can't see system properties yet, so pull
// the system locale out of the mount service.
if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
copyLocaleFromMountService();
}
-
- // Let package manager load internal ASECs.
- if (ASEC_ENABLE) {
- mPms.scanAvailableAsecs();
- }
-
- // Notify people waiting for ASECs to be scanned that it's done.
- mAsecsScanned.countDown();
}
private void copyLocaleFromMountService() {
@@ -1114,148 +944,6 @@ class StorageManagerService extends IStorageManager.Stub
SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
}
- /**
- * Callback from NativeDaemonConnector
- */
- @Override
- public boolean onCheckHoldWakeLock(int code) {
- return false;
- }
-
- /**
- * Callback from NativeDaemonConnector
- */
- @Override
- public boolean onEvent(int code, String raw, String[] cooked) {
- synchronized (mLock) {
- try {
- return onEventLocked(code, raw, cooked);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
- }
-
- private boolean onEventLocked(int code, String raw, String[] cooked) throws RemoteException {
- switch (code) {
- case VoldResponseCode.DISK_CREATED: {
- if (cooked.length != 3) break;
- final String diskId = cooked[1];
- final int flags = Integer.parseInt(cooked[2]);
- mListener.onDiskCreated(diskId, flags);
- break;
- }
- case VoldResponseCode.DISK_SIZE_CHANGED: {
- if (cooked.length != 3) break;
- final DiskInfo disk = mDisks.get(cooked[1]);
- if (disk != null) {
- disk.size = Long.parseLong(cooked[2]);
- }
- break;
- }
- case VoldResponseCode.DISK_LABEL_CHANGED: {
- final DiskInfo disk = mDisks.get(cooked[1]);
- if (disk != null) {
- final StringBuilder builder = new StringBuilder();
- for (int i = 2; i < cooked.length; i++) {
- builder.append(cooked[i]).append(' ');
- }
- disk.label = builder.toString().trim();
- }
- break;
- }
- case VoldResponseCode.DISK_SCANNED: {
- if (cooked.length != 2) break;
- final String diskId = cooked[1];
- mListener.onDiskScanned(diskId);
- break;
- }
- case VoldResponseCode.DISK_SYS_PATH_CHANGED: {
- if (cooked.length != 3) break;
- final DiskInfo disk = mDisks.get(cooked[1]);
- if (disk != null) {
- disk.sysPath = cooked[2];
- }
- break;
- }
- case VoldResponseCode.DISK_DESTROYED: {
- if (cooked.length != 2) break;
- final String diskId = cooked[1];
- mListener.onDiskDestroyed(diskId);
- break;
- }
-
- case VoldResponseCode.VOLUME_CREATED: {
- final String volId = cooked[1];
- final int type = Integer.parseInt(cooked[2]);
- final String diskId = TextUtils.nullIfEmpty(cooked[3]);
- final String partGuid = TextUtils.nullIfEmpty(cooked[4]);
- mListener.onVolumeCreated(volId, type, diskId, partGuid);
- break;
- }
- case VoldResponseCode.VOLUME_STATE_CHANGED: {
- if (cooked.length != 3) break;
- final String volId = cooked[1];
- final int state = Integer.parseInt(cooked[2]);
- mListener.onVolumeStateChanged(volId, state);
- break;
- }
- case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
- if (vol != null) {
- vol.fsType = cooked[2];
- }
- break;
- }
- case VoldResponseCode.VOLUME_FS_UUID_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
- if (vol != null) {
- vol.fsUuid = cooked[2];
- }
- break;
- }
- case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: {
- final VolumeInfo vol = mVolumes.get(cooked[1]);
- if (vol != null) {
- final StringBuilder builder = new StringBuilder();
- for (int i = 2; i < cooked.length; i++) {
- builder.append(cooked[i]).append(' ');
- }
- vol.fsLabel = builder.toString().trim();
- }
- // TODO: notify listeners that label changed
- break;
- }
- case VoldResponseCode.VOLUME_PATH_CHANGED: {
- if (cooked.length != 3) break;
- final String volId = cooked[1];
- final String path = cooked[2];
- mListener.onVolumePathChanged(volId, path);
- break;
- }
- case VoldResponseCode.VOLUME_INTERNAL_PATH_CHANGED: {
- if (cooked.length != 3) break;
- final String volId = cooked[1];
- final String internalPath = cooked[2];
- mListener.onVolumeInternalPathChanged(volId, internalPath);
- break;
- }
- case VoldResponseCode.VOLUME_DESTROYED: {
- if (cooked.length != 2) break;
- final String volId = cooked[1];
- mListener.onVolumeDestroyed(volId);
- break;
- }
- default: {
- Slog.d(TAG, "Unhandled vold event " + code);
- }
- }
-
- return true;
- }
-
private final IVoldListener mListener = new IVoldListener.Stub() {
@Override
public void onDiskCreated(String diskId, int flags) {
@@ -1654,24 +1342,6 @@ class StorageManagerService extends IStorageManager.Stub
LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
- /*
- * Create the connection to vold with a maximum queue of twice the
- * amount of containers we'd ever expect to have. This keeps an
- * "asec list" from blocking a thread repeatedly.
- */
-
- mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
- null);
- mConnector.setDebug(true);
- mConnector.setWarnIfHeld(mLock);
- mConnectorThread = new Thread(mConnector, VOLD_TAG);
-
- // Reuse parameters from first connector since they are tested and safe
- mCryptConnector = new NativeDaemonConnector(this, "cryptd",
- MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
- mCryptConnector.setDebug(true);
- mCryptConnectorThread = new Thread(mCryptConnector, CRYPTD_TAG);
-
final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_ADDED);
userFilter.addAction(Intent.ACTION_USER_REMOVED);
@@ -1689,8 +1359,6 @@ class StorageManagerService extends IStorageManager.Stub
private void start() {
connect();
- mConnectorThread.start();
- mCryptConnectorThread.start();
}
private void connect() {
@@ -1713,6 +1381,7 @@ class StorageManagerService extends IStorageManager.Stub
mVold = IVold.Stub.asInterface(binder);
try {
mVold.setListener(mListener);
+ onDaemonConnected();
return;
} catch (RemoteException e) {
Slog.w(TAG, "vold listener rejected; trying again", e);
@@ -1908,18 +1577,13 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void mount(String volId) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
if (isMountDisallowed(vol)) {
throw new SecurityException("Mounting " + volId + " restricted by policy");
}
try {
- if (ENABLE_BINDER) {
- mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
- } else {
- mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId);
- }
+ mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -1928,7 +1592,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void unmount(String volId) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
@@ -1948,11 +1611,7 @@ class StorageManagerService extends IStorageManager.Stub
}
try {
- if (ENABLE_BINDER) {
- mVold.unmount(vol.id);
- } else {
- mConnector.execute("volume", "unmount", vol.id);
- }
+ mVold.unmount(vol.id);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -1961,15 +1620,10 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void format(String volId) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
- waitForReady();
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
try {
- if (ENABLE_BINDER) {
- mVold.format(vol.id, "auto");
- } else {
- mConnector.execute("volume", "format", vol.id, "auto");
- }
+ mVold.format(vol.id, "auto");
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -1978,7 +1632,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public long benchmark(String volId) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
- waitForReady();
// TODO: refactor for callers to provide a listener
try {
@@ -2022,15 +1675,10 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void partitionPublic(String diskId) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
- waitForReady();
final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
try {
- if (ENABLE_BINDER) {
- mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
- } else {
- mConnector.execute("volume", "partition", diskId, "public");
- }
+ mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -2041,15 +1689,10 @@ class StorageManagerService extends IStorageManager.Stub
public void partitionPrivate(String diskId) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
enforceAdminUser();
- waitForReady();
final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
try {
- if (ENABLE_BINDER) {
- mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
- } else {
- mConnector.execute("volume", "partition", diskId, "private");
- }
+ mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -2060,15 +1703,10 @@ class StorageManagerService extends IStorageManager.Stub
public void partitionMixed(String diskId, int ratio) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
enforceAdminUser();
- waitForReady();
final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
try {
- if (ENABLE_BINDER) {
- mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
- } else {
- mConnector.execute("volume", "partition", diskId, "mixed", ratio);
- }
+ mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -2078,7 +1716,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void setVolumeNickname(String fsUuid, String nickname) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
Preconditions.checkNotNull(fsUuid);
synchronized (mLock) {
@@ -2092,7 +1729,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
Preconditions.checkNotNull(fsUuid);
synchronized (mLock) {
@@ -2106,7 +1742,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void forgetVolume(String fsUuid) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
Preconditions.checkNotNull(fsUuid);
@@ -2131,7 +1766,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void forgetAllVolumes() {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
synchronized (mLock) {
for (int i = 0; i < mRecords.size(); i++) {
@@ -2155,11 +1789,7 @@ class StorageManagerService extends IStorageManager.Stub
private void forgetPartition(String partGuid) {
try {
- if (ENABLE_BINDER) {
- mVold.forgetPartition(partGuid);
- } else {
- mConnector.execute("volume", "forget_partition", partGuid);
- }
+ mVold.forgetPartition(partGuid);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -2168,14 +1798,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void fstrim(int flags) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
- waitForReady();
-
- String cmd;
- if ((flags & StorageManager.FSTRIM_FLAG_DEEP) != 0) {
- cmd = "dodtrim";
- } else {
- cmd = "dotrim";
- }
try {
mVold.fstrim(flags, new IVoldTaskListener.Stub() {
@@ -2212,27 +1834,8 @@ class StorageManagerService extends IStorageManager.Stub
}
private void remountUidExternalStorage(int uid, int mode) {
- waitForReady();
-
- String modeName = "none";
- switch (mode) {
- case Zygote.MOUNT_EXTERNAL_DEFAULT: {
- modeName = "default";
- } break;
- case Zygote.MOUNT_EXTERNAL_READ: {
- modeName = "read";
- } break;
- case Zygote.MOUNT_EXTERNAL_WRITE: {
- modeName = "write";
- } break;
- }
-
try {
- if (ENABLE_BINDER) {
- mVold.remountUid(uid, mode);
- } else {
- mConnector.execute("volume", "remount_uid", uid, modeName);
- }
+ mVold.remountUid(uid, mode);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -2241,7 +1844,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void setDebugFlags(int flags, int mask) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
if (!EMULATE_FBE_SUPPORTED) {
@@ -2331,7 +1933,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
final VolumeInfo from;
final VolumeInfo to;
@@ -2405,29 +2006,7 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public int[] getStorageUsers(String path) {
- enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- waitForReady();
- try {
- final String[] r = NativeDaemonEvent.filterMessageList(
- mConnector.executeForList("storage", "users", path),
- VoldResponseCode.StorageUsersListResult);
-
- // FMT: <pid> <process name>
- int[] data = new int[r.length];
- for (int i = 0; i < r.length; i++) {
- String[] tok = r[i].split(" ");
- try {
- data[i] = Integer.parseInt(tok[0]);
- } catch (NumberFormatException nfe) {
- Slog.e(TAG, String.format("Error parsing pid %s", tok[0]));
- return new int[0];
- }
- }
- return data;
- } catch (NativeDaemonConnectorException e) {
- Slog.e(TAG, "Failed to retrieve storage users list", e);
- return new int[0];
- }
+ throw new UnsupportedOperationException();
}
private void warnOnNotMounted() {
@@ -2444,290 +2023,65 @@ class StorageManagerService extends IStorageManager.Stub
Slog.w(TAG, "No primary storage mounted!");
}
+ @Override
public String[] getSecureContainerList() {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_ACCESS);
- waitForReady();
- warnOnNotMounted();
-
- try {
- return NativeDaemonEvent.filterMessageList(
- mConnector.executeForList("asec", "list"), VoldResponseCode.AsecListResult);
- } catch (NativeDaemonConnectorException e) {
- return new String[0];
- }
+ throw new UnsupportedOperationException();
}
+ @Override
public int createSecureContainer(String id, int sizeMb, String fstype, String key,
int ownerUid, boolean external) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_CREATE);
- waitForReady();
- warnOnNotMounted();
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- mConnector.execute("asec", "create", id, sizeMb, fstype, new SensitiveArg(key),
- ownerUid, external ? "1" : "0");
- } catch (NativeDaemonConnectorException e) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
-
- if (rc == StorageResultCode.OperationSucceeded) {
- synchronized (mAsecMountSet) {
- mAsecMountSet.add(id);
- }
- }
- return rc;
+ throw new UnsupportedOperationException();
}
@Override
public int resizeSecureContainer(String id, int sizeMb, String key) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_CREATE);
- waitForReady();
- warnOnNotMounted();
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- mConnector.execute("asec", "resize", id, sizeMb, new SensitiveArg(key));
- } catch (NativeDaemonConnectorException e) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public int finalizeSecureContainer(String id) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_CREATE);
- warnOnNotMounted();
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- mConnector.execute("asec", "finalize", id);
- /*
- * Finalization does a remount, so no need
- * to update mAsecMountSet
- */
- } catch (NativeDaemonConnectorException e) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public int fixPermissionsSecureContainer(String id, int gid, String filename) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_CREATE);
- warnOnNotMounted();
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- mConnector.execute("asec", "fixperms", id, gid, filename);
- /*
- * Fix permissions does a remount, so no need to update
- * mAsecMountSet
- */
- } catch (NativeDaemonConnectorException e) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public int destroySecureContainer(String id, boolean force) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_DESTROY);
- waitForReady();
- warnOnNotMounted();
-
- /*
- * Force a GC to make sure AssetManagers in other threads of the
- * system_server are cleaned up. We have to do this since AssetManager
- * instances are kept as a WeakReference and it's possible we have files
- * open on the external storage.
- */
- Runtime.getRuntime().gc();
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- final Command cmd = new Command("asec", "destroy", id);
- if (force) {
- cmd.appendArg("force");
- }
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedStorageBusy) {
- rc = StorageResultCode.OperationFailedStorageBusy;
- } else {
- rc = StorageResultCode.OperationFailedInternalError;
- }
- }
-
- if (rc == StorageResultCode.OperationSucceeded) {
- synchronized (mAsecMountSet) {
- if (mAsecMountSet.contains(id)) {
- mAsecMountSet.remove(id);
- }
- }
- }
-
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
- waitForReady();
- warnOnNotMounted();
-
- synchronized (mAsecMountSet) {
- if (mAsecMountSet.contains(id)) {
- return StorageResultCode.OperationFailedStorageMounted;
- }
- }
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid,
- readOnly ? "ro" : "rw");
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code != VoldResponseCode.OpFailedStorageBusy) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
- }
-
- if (rc == StorageResultCode.OperationSucceeded) {
- synchronized (mAsecMountSet) {
- mAsecMountSet.add(id);
- }
- }
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public int unmountSecureContainer(String id, boolean force) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
- waitForReady();
- warnOnNotMounted();
-
- synchronized (mAsecMountSet) {
- if (!mAsecMountSet.contains(id)) {
- return StorageResultCode.OperationFailedStorageNotMounted;
- }
- }
-
- /*
- * Force a GC to make sure AssetManagers in other threads of the
- * system_server are cleaned up. We have to do this since AssetManager
- * instances are kept as a WeakReference and it's possible we have files
- * open on the external storage.
- */
- Runtime.getRuntime().gc();
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- final Command cmd = new Command("asec", "unmount", id);
- if (force) {
- cmd.appendArg("force");
- }
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedStorageBusy) {
- rc = StorageResultCode.OperationFailedStorageBusy;
- } else {
- rc = StorageResultCode.OperationFailedInternalError;
- }
- }
-
- if (rc == StorageResultCode.OperationSucceeded) {
- synchronized (mAsecMountSet) {
- mAsecMountSet.remove(id);
- }
- }
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public boolean isSecureContainerMounted(String id) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_ACCESS);
- waitForReady();
- warnOnNotMounted();
-
- synchronized (mAsecMountSet) {
- return mAsecMountSet.contains(id);
- }
+ throw new UnsupportedOperationException();
}
+ @Override
public int renameSecureContainer(String oldId, String newId) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_RENAME);
- waitForReady();
- warnOnNotMounted();
-
- synchronized (mAsecMountSet) {
- /*
- * Because a mounted container has active internal state which cannot be
- * changed while active, we must ensure both ids are not currently mounted.
- */
- if (mAsecMountSet.contains(oldId) || mAsecMountSet.contains(newId)) {
- return StorageResultCode.OperationFailedStorageMounted;
- }
- }
-
- int rc = StorageResultCode.OperationSucceeded;
- try {
- mConnector.execute("asec", "rename", oldId, newId);
- } catch (NativeDaemonConnectorException e) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
-
- return rc;
+ throw new UnsupportedOperationException();
}
+ @Override
public String getSecureContainerPath(String id) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_ACCESS);
- waitForReady();
- warnOnNotMounted();
-
- final NativeDaemonEvent event;
- try {
- event = mConnector.execute("asec", "path", id);
- event.checkCode(VoldResponseCode.AsecPathResult);
- return event.getMessage();
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedStorageNotFound) {
- Slog.i(TAG, String.format("Container '%s' not found", id));
- return null;
- } else {
- throw new IllegalStateException(String.format("Unexpected response code %d", code));
- }
- }
+ throw new UnsupportedOperationException();
}
+ @Override
public String getSecureContainerFilesystemPath(String id) {
- if (!ASEC_ENABLE) throw new UnsupportedOperationException();
- enforcePermission(android.Manifest.permission.ASEC_ACCESS);
- waitForReady();
- warnOnNotMounted();
-
- final NativeDaemonEvent event;
- try {
- event = mConnector.execute("asec", "fspath", id);
- event.checkCode(VoldResponseCode.AsecPathResult);
- return event.getMessage();
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedStorageNotFound) {
- Slog.i(TAG, String.format("Container '%s' not found", id));
- return null;
- } else {
- throw new IllegalStateException(String.format("Unexpected response code %d", code));
- }
- }
+ throw new UnsupportedOperationException();
}
@Override
@@ -2762,10 +2116,10 @@ class StorageManagerService extends IStorageManager.Stub
return callerUid == packageUid;
}
+ @Override
public String getMountedObbPath(String rawPath) {
Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
- waitForReady();
warnOnNotMounted();
final ObbState state;
@@ -2777,23 +2131,7 @@ class StorageManagerService extends IStorageManager.Stub
return null;
}
- if (ENABLE_BINDER) {
- return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
- }
-
- final NativeDaemonEvent event;
- try {
- event = mConnector.execute("obb", "path", state.canonicalPath);
- event.checkCode(VoldResponseCode.AsecPathResult);
- return event.getMessage();
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedStorageNotFound) {
- return null;
- } else {
- throw new IllegalStateException(String.format("Unexpected response code %d", code));
- }
- }
+ return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
}
@Override
@@ -2850,28 +2188,10 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
- if (ENABLE_BINDER) {
- try {
- return mVold.fdeComplete();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "cryptocomplete");
- return Integer.parseInt(event.getMessage());
- } catch (NumberFormatException e) {
- // Bad result - unexpected.
- Slog.w(TAG, "Unable to parse result from cryptfs cryptocomplete");
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- } catch (NativeDaemonConnectorException e) {
- // Something bad happened.
- Slog.w(TAG, "Error in communicating with cryptfs in validating");
+ return mVold.fdeComplete();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
}
}
@@ -2881,8 +2201,6 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
if (TextUtils.isEmpty(password)) {
throw new IllegalArgumentException("password cannot be empty");
}
@@ -2891,55 +2209,27 @@ class StorageManagerService extends IStorageManager.Stub
Slog.i(TAG, "decrypting storage...");
}
- if (ENABLE_BINDER) {
- try {
- mVold.fdeCheckPassword(password);
- mHandler.postDelayed(() -> {
- try {
- mVold.fdeRestart();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- }
- }, DateUtils.SECOND_IN_MILLIS);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "checkpw", new SensitiveArg(password));
-
- final int code = Integer.parseInt(event.getMessage());
- if (code == 0) {
- // Decrypt was successful. Post a delayed message before restarting in order
- // to let the UI to clear itself
- mHandler.postDelayed(new Runnable() {
- public void run() {
- try {
- mCryptConnector.execute("cryptfs", "restart");
- } catch (NativeDaemonConnectorException e) {
- Slog.e(TAG, "problem executing in background", e);
- }
- }
- }, 1000); // 1 second
- }
-
- return code;
- } catch (NativeDaemonConnectorException e) {
- // Decryption failed
- return e.getCode();
+ mVold.fdeCheckPassword(password);
+ mHandler.postDelayed(() -> {
+ try {
+ mVold.fdeRestart();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ }
+ }, DateUtils.SECOND_IN_MILLIS);
+ return 0;
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
}
}
+ @Override
public int encryptStorage(int type, String password) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
password = "";
} else if (TextUtils.isEmpty(password)) {
@@ -2951,17 +2241,7 @@ class StorageManagerService extends IStorageManager.Stub
}
try {
- if (ENABLE_BINDER) {
- mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
- } else {
- if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
- mCryptConnector.execute("cryptfs", "enablecrypto", "inplace",
- CRYPTO_TYPES[type]);
- } else {
- mCryptConnector.execute("cryptfs", "enablecrypto", "inplace",
- CRYPTO_TYPES[type], new SensitiveArg(password));
- }
- }
+ mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
} catch (Exception e) {
Slog.wtf(TAG, e);
return -1;
@@ -2974,12 +2254,11 @@ class StorageManagerService extends IStorageManager.Stub
* @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
* @param password The password to set.
*/
+ @Override
public int changeEncryptionPassword(int type, String password) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
password = "";
} else if (TextUtils.isEmpty(password)) {
@@ -2990,23 +2269,12 @@ class StorageManagerService extends IStorageManager.Stub
Slog.i(TAG, "changing encryption password...");
}
- if (ENABLE_BINDER) {
- try {
- mVold.fdeChangePassword(type, password);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
try {
- NativeDaemonEvent event = mCryptConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type],
- new SensitiveArg(password));
- return Integer.parseInt(event.getMessage());
- } catch (NativeDaemonConnectorException e) {
- // Encryption failed
- return e.getCode();
+ mVold.fdeChangePassword(type, password);
+ return 0;
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return -1;
}
}
@@ -3027,30 +2295,16 @@ class StorageManagerService extends IStorageManager.Stub
throw new IllegalArgumentException("password cannot be empty");
}
- waitForReady();
-
if (DEBUG_EVENTS) {
Slog.i(TAG, "validating encryption password...");
}
- if (ENABLE_BINDER) {
- try {
- mVold.fdeVerifyPassword(password);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "verifypw", new SensitiveArg(password));
- Slog.i(TAG, "cryptfs verifypw => " + event.getMessage());
- return Integer.parseInt(event.getMessage());
- } catch (NativeDaemonConnectorException e) {
- // Encryption failed
- return e.getCode();
+ mVold.fdeVerifyPassword(password);
+ return 0;
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return -1;
}
}
@@ -3063,28 +2317,11 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
- if (ENABLE_BINDER) {
- try {
- return mVold.fdeGetPasswordType();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "getpwtype");
- for (int i = 0; i < CRYPTO_TYPES.length; ++i) {
- if (CRYPTO_TYPES[i].equals(event.getMessage()))
- return i;
- }
-
- throw new IllegalStateException("unexpected return from cryptfs");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ return mVold.fdeGetPasswordType();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return -1;
}
}
@@ -3098,23 +2335,12 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
- if (ENABLE_BINDER) {
- try {
- mVold.fdeSetField(field, contents);
- return;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "setfield", field, contents);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mVold.fdeSetField(field, contents);
+ return;
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return;
}
}
@@ -3128,29 +2354,11 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
- if (ENABLE_BINDER) {
- try {
- return mVold.fdeGetField(field);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return null;
- }
- }
-
- final NativeDaemonEvent event;
try {
- final String[] contents = NativeDaemonEvent.filterMessageList(
- mCryptConnector.executeForList("cryptfs", "getfield", field),
- VoldResponseCode.CryptfsGetfieldResult);
- String result = new String();
- for (String content : contents) {
- result += content;
- }
- return result;
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ return mVold.fdeGetField(field);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return null;
}
}
@@ -3163,23 +2371,11 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
- waitForReady();
-
- if (ENABLE_BINDER) {
- try {
- return mVold.isConvertibleToFbe();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return false;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "isConvertibleToFBE");
- return Integer.parseInt(event.getMessage()) != 0;
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ return mVold.isConvertibleToFbe();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return false;
}
}
@@ -3188,31 +2384,10 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"only keyguard can retrieve password");
- if (!isReady()) {
- return new String();
- }
-
- if (ENABLE_BINDER) {
- try {
- return mVold.fdeGetPassword();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return null;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "getpw");
- if ("-1".equals(event.getMessage())) {
- // -1 equals no password
- return null;
- }
- return event.getMessage();
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Invalid response to getPassword");
+ return mVold.fdeGetPassword();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
return null;
}
}
@@ -3222,40 +2397,21 @@ class StorageManagerService extends IStorageManager.Stub
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"only keyguard can clear password");
- if (!isReady()) {
- return;
- }
-
- if (ENABLE_BINDER) {
- try {
- mVold.fdeClearPassword();
- return;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return;
- }
- }
-
- final NativeDaemonEvent event;
try {
- event = mCryptConnector.execute("cryptfs", "clearpw");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mVold.fdeClearPassword();
+ return;
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ return;
}
}
@Override
public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.createUserKey(userId, serialNumber, ephemeral);
- } else {
- mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber,
- ephemeral ? 1 : 0);
- }
+ mVold.createUserKey(userId, serialNumber, ephemeral);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3264,14 +2420,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void destroyUserKey(int userId) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.destroyUserKey(userId);
- } else {
- mCryptConnector.execute("cryptfs", "destroy_user_key", userId);
- }
+ mVold.destroyUserKey(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3295,16 +2446,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
- } else {
- mCryptConnector.execute("cryptfs", "add_user_key_auth", userId, serialNumber,
- new SensitiveArg(encodeBytes(token)),
- new SensitiveArg(encodeBytes(secret)));
- }
+ mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3316,14 +2460,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void fixateNewestUserKeyAuth(int userId) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.fixateNewestUserKeyAuth(userId);
- } else {
- mCryptConnector.execute("cryptfs", "fixate_newest_user_key_auth", userId);
- }
+ mVold.fixateNewestUserKeyAuth(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3332,7 +2471,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
// When a user has secure lock screen, require secret to actually unlock.
@@ -3342,14 +2480,8 @@ class StorageManagerService extends IStorageManager.Stub
}
try {
- if (ENABLE_BINDER) {
- mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
- encodeBytes(secret));
- } else {
- mCryptConnector.execute("cryptfs", "unlock_user_key", userId, serialNumber,
- new SensitiveArg(encodeBytes(token)),
- new SensitiveArg(encodeBytes(secret)));
- }
+ mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
+ encodeBytes(secret));
} catch (Exception e) {
Slog.wtf(TAG, e);
return;
@@ -3369,14 +2501,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void lockUserKey(int userId) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.lockUserKey(userId);
- } else {
- mCryptConnector.execute("cryptfs", "lock_user_key", userId);
- }
+ mVold.lockUserKey(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
return;
@@ -3397,15 +2524,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
- } else {
- mCryptConnector.execute("cryptfs", "prepare_user_storage", escapeNull(volumeUuid),
- userId, serialNumber, flags);
- }
+ mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3414,15 +2535,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void destroyUserStorage(String volumeUuid, int userId, int flags) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.destroyUserStorage(volumeUuid, userId, flags);
- } else {
- mCryptConnector.execute("cryptfs", "destroy_user_storage", escapeNull(volumeUuid),
- userId, flags);
- }
+ mVold.destroyUserStorage(volumeUuid, userId, flags);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3431,14 +2546,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void secdiscard(String path) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
try {
- if (ENABLE_BINDER) {
- mVold.secdiscard(path);
- } else {
- mCryptConnector.execute("cryptfs", "secdiscard", escapeNull(path));
- }
+ mVold.secdiscard(path);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3453,33 +2563,18 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
- if (ENABLE_BINDER) {
- try {
- return new ParcelFileDescriptor(
- mVold.mountAppFuse(uid, Process.myPid(), mountId));
- } catch (Exception e) {
- throw new NativeDaemonConnectorException("Failed to mount", e);
- }
- } else {
- final NativeDaemonEvent event = mConnector.execute(
- "appfuse", "mount", uid, Process.myPid(), mountId);
- opened = true;
- if (event.getFileDescriptors() == null ||
- event.getFileDescriptors().length == 0) {
- throw new NativeDaemonConnectorException("Cannot obtain device FD");
- }
- return new ParcelFileDescriptor(event.getFileDescriptors()[0]);
+ try {
+ return new ParcelFileDescriptor(
+ mVold.mountAppFuse(uid, Process.myPid(), mountId));
+ } catch (Exception e) {
+ throw new NativeDaemonConnectorException("Failed to mount", e);
}
}
@Override
public void close() throws Exception {
if (opened) {
- if (ENABLE_BINDER) {
- mVold.unmountAppFuse(uid, Process.myPid(), mountId);
- } else {
- mConnector.execute("appfuse", "unmount", uid, Process.myPid(), mountId);
- }
+ mVold.unmountAppFuse(uid, Process.myPid(), mountId);
opened = false;
}
}
@@ -3568,11 +2663,7 @@ class StorageManagerService extends IStorageManager.Stub
}
try {
- if (ENABLE_BINDER) {
- mVold.mkdirs(appPath);
- } else {
- mConnector.execute("volume", "mkdirs", appPath);
- }
+ mVold.mkdirs(appPath);
return 0;
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -4124,7 +3215,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void handleExecute() throws IOException, RemoteException {
- waitForReady();
warnOnNotMounted();
final ObbInfo obbInfo = getObbInfo();
@@ -4174,19 +3264,9 @@ class StorageManagerService extends IStorageManager.Stub
int rc = StorageResultCode.OperationSucceeded;
try {
- if (ENABLE_BINDER) {
- mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
- mObbState.ownerGid);
- mVold.mount(mObbState.volId, 0, -1);
- } else {
- mConnector.execute("obb", "mount", mObbState.canonicalPath,
- new SensitiveArg(hashedKey), mObbState.ownerGid);
- }
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code != VoldResponseCode.OpFailedStorageBusy) {
- rc = StorageResultCode.OperationFailedInternalError;
- }
+ mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
+ mObbState.ownerGid);
+ mVold.mount(mObbState.volId, 0, -1);
} catch (Exception e) {
Slog.w(TAG, e);
rc = StorageResultCode.OperationFailedInternalError;
@@ -4233,7 +3313,6 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void handleExecute() throws IOException {
- waitForReady();
warnOnNotMounted();
final ObbState existingState;
@@ -4255,27 +3334,9 @@ class StorageManagerService extends IStorageManager.Stub
int rc = StorageResultCode.OperationSucceeded;
try {
- if (ENABLE_BINDER) {
- mVold.unmount(mObbState.volId);
- mVold.destroyObb(mObbState.volId);
- mObbState.volId = null;
- } else {
- final Command cmd = new Command("obb", "unmount", mObbState.canonicalPath);
- if (mForceUnmount) {
- cmd.appendArg("force");
- }
- mConnector.execute(cmd);
- }
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedStorageBusy) {
- rc = StorageResultCode.OperationFailedStorageBusy;
- } else if (code == VoldResponseCode.OpFailedStorageNotFound) {
- // If it's not mounted then we've already won.
- rc = StorageResultCode.OperationSucceeded;
- } else {
- rc = StorageResultCode.OperationFailedInternalError;
- }
+ mVold.unmount(mObbState.volId);
+ mVold.destroyObb(mObbState.volId);
+ mObbState.volId = null;
} catch (Exception e) {
Slog.w(TAG, e);
rc = StorageResultCode.OperationFailedInternalError;
@@ -4506,18 +3567,6 @@ class StorageManagerService extends IStorageManager.Stub
}
pw.println();
- pw.println("mConnector:");
- pw.increaseIndent();
- mConnector.dump(fd, pw, args);
- pw.decreaseIndent();
-
- pw.println();
- pw.println("mCryptConnector:");
- pw.increaseIndent();
- mCryptConnector.dump(fd, pw, args);
- pw.decreaseIndent();
-
- pw.println();
pw.print("Last maintenance: ");
pw.println(TimeUtils.formatForLogging(mLastMaintenance));
}
@@ -4525,11 +3574,10 @@ class StorageManagerService extends IStorageManager.Stub
/** {@inheritDoc} */
@Override
public void monitor() {
- if (mConnector != null) {
- mConnector.monitor();
- }
- if (mCryptConnector != null) {
- mCryptConnector.monitor();
+ try {
+ mVold.monitor();
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index e0cde72ffff2..90ad8a5d0131 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2162,6 +2162,15 @@ public final class ActiveServices {
}
}
+ if (r.fgRequired) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
+ + " for fg-service launch");
+ }
+ mAm.tempWhitelistUidLocked(r.appInfo.uid,
+ SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
+ }
+
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c8e2dc57e0ed..5d200ae91e25 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -709,7 +709,7 @@ public class ActivityManagerService extends IActivityManager.Stub
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
- && !mKeyguardController.isKeyguardShowing()
+ && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
&& !(UserManager.isDeviceInDemoMode(mContext)
&& mUserController.getCurrentUser().isDemo());
}
@@ -1648,45 +1648,32 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int DISPATCH_PROCESSES_CHANGED_UI_MSG = 31;
static final int DISPATCH_PROCESS_DIED_UI_MSG = 32;
static final int REPORT_MEM_USAGE_MSG = 33;
- static final int REPORT_USER_SWITCH_MSG = 34;
- static final int CONTINUE_USER_SWITCH_MSG = 35;
- static final int USER_SWITCH_TIMEOUT_MSG = 36;
static final int IMMERSIVE_MODE_LOCK_MSG = 37;
static final int PERSIST_URI_GRANTS_MSG = 38;
static final int REQUEST_ALL_PSS_MSG = 39;
- static final int START_PROFILES_MSG = 40;
static final int UPDATE_TIME_PREFERENCE_MSG = 41;
- static final int SYSTEM_USER_START_MSG = 42;
- static final int SYSTEM_USER_CURRENT_MSG = 43;
static final int ENTER_ANIMATION_COMPLETE_MSG = 44;
static final int FINISH_BOOTING_MSG = 45;
- static final int START_USER_SWITCH_UI_MSG = 46;
static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47;
static final int DISMISS_DIALOG_UI_MSG = 48;
static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49;
static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50;
static final int DELETE_DUMPHEAP_MSG = 51;
- static final int FOREGROUND_PROFILE_CHANGED_MSG = 52;
static final int DISPATCH_UIDS_CHANGED_UI_MSG = 53;
static final int REPORT_TIME_TRACKER_MSG = 54;
- static final int REPORT_USER_SWITCH_COMPLETE_MSG = 55;
static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 56;
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 57;
static final int IDLE_UIDS_MSG = 58;
- static final int SYSTEM_USER_UNLOCK_MSG = 59;
static final int LOG_STACK_STATE = 60;
static final int VR_MODE_CHANGE_MSG = 61;
static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 62;
static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 63;
- static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 64;
static final int NOTIFY_VR_SLEEPING_MSG = 65;
static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
- static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 71;
- static final int START_USER_SWITCH_FG_MSG = 712;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1899,10 +1886,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
break;
}
- case START_USER_SWITCH_UI_MSG: {
- mUserController.showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj);
- break;
- }
case DISMISS_DIALOG_UI_MSG: {
final Dialog d = (Dialog) msg.obj;
d.dismiss();
@@ -2131,26 +2114,6 @@ public class ActivityManagerService extends IActivityManager.Stub
thread.start();
break;
}
- case START_USER_SWITCH_FG_MSG: {
- mUserController.startUserInForeground(msg.arg1);
- break;
- }
- case REPORT_USER_SWITCH_MSG: {
- mUserController.dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case CONTINUE_USER_SWITCH_MSG: {
- mUserController.continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case USER_SWITCH_TIMEOUT_MSG: {
- mUserController.timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case USER_SWITCH_CALLBACKS_TIMEOUT_MSG: {
- mUserController.timeoutUserSwitchCallbacks(msg.arg1, msg.arg2);
- break;
- }
case IMMERSIVE_MODE_LOCK_MSG: {
final boolean nextState = (msg.arg1 != 0);
if (mUpdateLock.isHeld() != nextState) {
@@ -2175,12 +2138,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
break;
}
- case START_PROFILES_MSG: {
- synchronized (ActivityManagerService.this) {
- mUserController.startProfilesLocked();
- }
- break;
- }
case UPDATE_TIME_PREFERENCE_MSG: {
// The user's time format preference might have changed.
// For convenience we re-use the Intent extra values.
@@ -2199,35 +2156,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
break;
}
- case SYSTEM_USER_START_MSG: {
- mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
- Integer.toString(msg.arg1), msg.arg1);
- mSystemServiceManager.startUser(msg.arg1);
- break;
- }
- case SYSTEM_USER_UNLOCK_MSG: {
- final int userId = msg.arg1;
- mSystemServiceManager.unlockUser(userId);
- synchronized (ActivityManagerService.this) {
- mRecentTasks.loadUserRecentsLocked(userId);
- }
- if (userId == UserHandle.USER_SYSTEM) {
- startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- }
- installEncryptionUnawareProviders(userId);
- mUserController.finishUserUnlocked((UserState) msg.obj);
- break;
- }
- case SYSTEM_USER_CURRENT_MSG: {
- mBatteryStatsService.noteEvent(
- BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
- Integer.toString(msg.arg2), msg.arg2);
- mBatteryStatsService.noteEvent(
- BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
- Integer.toString(msg.arg1), msg.arg1);
- mSystemServiceManager.switchUser(msg.arg1);
- break;
- }
case ENTER_ANIMATION_COMPLETE_MSG: {
synchronized (ActivityManagerService.this) {
ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
@@ -2367,19 +2295,10 @@ public class ActivityManagerService extends IActivityManager.Stub
mMemWatchDumpUid = -1;
}
} break;
- case FOREGROUND_PROFILE_CHANGED_MSG: {
- mUserController.dispatchForegroundProfileChanged(msg.arg1);
- } break;
case REPORT_TIME_TRACKER_MSG: {
AppTimeTracker tracker = (AppTimeTracker)msg.obj;
tracker.deliverResult(mContext);
} break;
- case REPORT_USER_SWITCH_COMPLETE_MSG: {
- mUserController.dispatchUserSwitchComplete(msg.arg1);
- } break;
- case REPORT_LOCKED_BOOT_COMPLETE_MSG: {
- mUserController.dispatchLockedBootComplete(msg.arg1);
- } break;
case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: {
IUiAutomationConnection connection = (IUiAutomationConnection) msg.obj;
try {
@@ -3147,9 +3066,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) {
- mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
- mHandler.obtainMessage(
- FOREGROUND_PROFILE_CHANGED_MSG, r.userId, 0).sendToTarget();
+ mUserController.sendForegroundProfileChanged(r.userId);
}
mLastResumedActivity = r;
@@ -3869,6 +3786,12 @@ public class ActivityManagerService extends IActivityManager.Stub
mNativeDebuggingApp = null;
}
+ if (app.info.isPrivilegedApp() &&
+ !SystemProperties.getBoolean("pm.dexopt.priv-apps", true)) {
+ runtimeFlags |= Zygote.DISABLE_VERIFIER;
+ runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
+ }
+
String invokeWith = null;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory.
@@ -4151,15 +4074,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- void enforceShellRestriction(String restriction, int userHandle) {
- if (Binder.getCallingUid() == SHELL_UID) {
- if (userHandle < 0 || mUserController.hasUserRestriction(restriction, userHandle)) {
- throw new SecurityException("Shell does not have permission to access user "
- + userHandle);
- }
- }
- }
-
@Override
public int getFrontActivityScreenCompatMode() {
enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
@@ -7366,7 +7280,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
});
- scheduleStartProfilesLocked();
+ mUserController.scheduleStartProfilesLocked();
}
}
}
@@ -10043,7 +9957,7 @@ public class ActivityManagerService extends IActivityManager.Stub
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"getTaskDescription()");
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
return tr.lastTaskDescription;
}
@@ -10156,7 +10070,7 @@ public class ActivityManagerService extends IActivityManager.Stub
public void setTaskResizeable(int taskId, int resizeableMode) {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
- taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
return;
@@ -10219,7 +10133,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
return rect;
@@ -10251,7 +10165,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
return;
@@ -10270,7 +10184,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "cancelTaskThumbnailTransition: taskId=" + taskId + " not found");
return;
@@ -10290,7 +10204,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final TaskRecord task;
synchronized (this) {
task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
return null;
@@ -10604,56 +10518,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- @Override
- public void swapDockedAndFullscreenStack() throws RemoteException {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "swapDockedAndFullscreenStack()");
- synchronized (this) {
- long ident = Binder.clearCallingIdentity();
- try {
- final ActivityStack fullscreenStack = mStackSupervisor.getStack(
- FULLSCREEN_WORKSPACE_STACK_ID);
- final TaskRecord topTask = fullscreenStack != null ? fullscreenStack.topTask()
- : null;
- final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
- final ArrayList<TaskRecord> tasks = dockedStack != null ? dockedStack.getAllTasks()
- : null;
- if (topTask == null || tasks == null || tasks.size() == 0) {
- Slog.w(TAG,
- "Unable to swap tasks, either docked or fullscreen stack is empty.");
- return;
- }
-
- // TODO: App transition
- mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_RELAUNCH, false);
-
- // Defer the resume until we move all the docked tasks to the fullscreen stack below
- topTask.reparent(DOCKED_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
- DEFER_RESUME, "swapDockedAndFullscreenStack - DOCKED_STACK");
- final int size = tasks.size();
- for (int i = 0; i < size; i++) {
- final int id = tasks.get(i).taskId;
- if (id == topTask.taskId) {
- continue;
- }
-
- // Defer the resume until after all the tasks have been moved
- tasks.get(i).reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
- REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, DEFER_RESUME,
- "swapDockedAndFullscreenStack - FULLSCREEN_STACK");
- }
-
- // Because we deferred the resume to avoid conflicts with stack switches while
- // resuming, we need to do it after all the tasks are moved.
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mStackSupervisor.resumeFocusedStackTopActivityLocked();
-
- mWindowManager.executeAppTransition();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
/**
* Moves the input task to the docked stack.
*
@@ -12066,7 +11930,7 @@ public class ActivityManagerService extends IActivityManager.Stub
//mUsageStatsService.monitorPackages();
}
- private void startPersistentApps(int matchFlags) {
+ void startPersistentApps(int matchFlags) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
synchronized (this) {
@@ -12087,7 +11951,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* When a user is unlocked, we need to install encryption-unaware providers
* belonging to any running apps.
*/
- private void installEncryptionUnawareProviders(int userId) {
+ void installEncryptionUnawareProviders(int userId) {
// We're only interested in providers that are encryption unaware, and
// we don't care about uninstalled apps, since there's no way they're
// running at this point.
@@ -12392,19 +12256,14 @@ public class ActivityManagerService extends IActivityManager.Stub
void onWakefulnessChanged(int wakefulness) {
synchronized(this) {
+ boolean wasAwake = mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
+ boolean isAwake = wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
mWakefulness = wakefulness;
- // Also update state in a special way for running foreground services UI.
- switch (mWakefulness) {
- case PowerManagerInternal.WAKEFULNESS_ASLEEP:
- case PowerManagerInternal.WAKEFULNESS_DREAMING:
- case PowerManagerInternal.WAKEFULNESS_DOZING:
- mServices.updateScreenStateLocked(false /* screenOn */);
- break;
- case PowerManagerInternal.WAKEFULNESS_AWAKE:
- default:
- mServices.updateScreenStateLocked(true /* screenOn */);
- break;
+ if (wasAwake != isAwake) {
+ // Also update state in a special way for running foreground services UI.
+ mServices.updateScreenStateLocked(isAwake);
+ sendNotifyVrManagerOfSleepState(!isAwake);
}
}
}
@@ -12440,7 +12299,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */);
if (wasSleeping) {
- sendNotifyVrManagerOfSleepState(false);
updateOomAdjLocked();
}
} else if (!mSleeping && shouldSleep) {
@@ -12450,7 +12308,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
mStackSupervisor.goingToSleepLocked();
- sendNotifyVrManagerOfSleepState(true);
updateOomAdjLocked();
}
}
@@ -12544,7 +12401,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public void setLockScreenShown(boolean showing) {
+ public void setLockScreenShown(boolean showing, int secondaryDisplayShowing) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -12554,7 +12411,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized(this) {
long ident = Binder.clearCallingIdentity();
try {
- mKeyguardController.setKeyguardShown(showing);
+ mKeyguardController.setKeyguardShown(showing, secondaryDisplayShowing);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -23559,54 +23416,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean switchUser(final int targetUserId) {
- enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId);
- int currentUserId;
- UserInfo targetUserInfo;
- synchronized (this) {
- currentUserId = mUserController.getCurrentUserIdLocked();
- targetUserInfo = mUserController.getUserInfo(targetUserId);
- if (targetUserId == currentUserId) {
- Slog.i(TAG, "user #" + targetUserId + " is already the current user");
- return true;
- }
- if (targetUserInfo == null) {
- Slog.w(TAG, "No user info for user #" + targetUserId);
- return false;
- }
- if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mContext)) {
- Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId
- + " when device is in demo mode");
- return false;
- }
- if (!targetUserInfo.supportsSwitchTo()) {
- Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
- return false;
- }
- if (targetUserInfo.isManagedProfile()) {
- Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
- return false;
- }
- mUserController.setTargetUserIdLocked(targetUserId);
- }
- if (mUserController.mUserSwitchUiEnabled) {
- UserInfo currentUserInfo = mUserController.getUserInfo(currentUserId);
- Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo);
- mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG);
- mUiHandler.sendMessage(mHandler.obtainMessage(
- START_USER_SWITCH_UI_MSG, userNames));
- } else {
- mHandler.removeMessages(START_USER_SWITCH_FG_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(
- START_USER_SWITCH_FG_MSG, targetUserId, 0));
- }
- return true;
- }
-
- void scheduleStartProfilesLocked() {
- if (!mHandler.hasMessages(START_PROFILES_MSG)) {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
- DateUtils.SECOND_IN_MILLIS);
- }
+ return mUserController.switchUser(targetUserId);
}
@Override
@@ -24018,7 +23828,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void notifyKeyguardTrustedChanged() {
synchronized (ActivityManagerService.this) {
- if (mKeyguardController.isKeyguardShowing()) {
+ if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 6901d2de6f00..0aca9ea6d748 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -75,6 +75,8 @@ import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
@@ -115,7 +117,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
private boolean mStreaming; // Streaming the profiling output to a file.
private String mAgent; // Agent to attach on startup.
private int mDisplayId;
- private int mStackId;
+ private int mWindowingMode;
+ private int mActivityType;
private int mTaskId;
private boolean mIsTaskOverlay;
@@ -271,7 +274,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
mStreaming = false;
mUserId = defUser;
mDisplayId = INVALID_DISPLAY;
- mStackId = INVALID_STACK_ID;
+ mWindowingMode = WINDOWING_MODE_UNDEFINED;
+ mActivityType = ACTIVITY_TYPE_UNDEFINED;
mTaskId = INVALID_TASK_ID;
mIsTaskOverlay = false;
@@ -308,8 +312,10 @@ final class ActivityManagerShellCommand extends ShellCommand {
mReceiverPermission = getNextArgRequired();
} else if (opt.equals("--display")) {
mDisplayId = Integer.parseInt(getNextArgRequired());
- } else if (opt.equals("--stack")) {
- mStackId = Integer.parseInt(getNextArgRequired());
+ } else if (opt.equals("--windowingMode")) {
+ mWindowingMode = Integer.parseInt(getNextArgRequired());
+ } else if (opt.equals("--activityType")) {
+ mActivityType = Integer.parseInt(getNextArgRequired());
} else if (opt.equals("--task")) {
mTaskId = Integer.parseInt(getNextArgRequired());
} else if (opt.equals("--task-overlay")) {
@@ -396,9 +402,17 @@ final class ActivityManagerShellCommand extends ShellCommand {
options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(mDisplayId);
}
- if (mStackId != INVALID_STACK_ID) {
- options = ActivityOptions.makeBasic();
- options.setLaunchStackId(mStackId);
+ if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ options.setLaunchWindowingMode(mWindowingMode);
+ }
+ if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ options.setLaunchActivityType(mActivityType);
}
if (mTaskId != INVALID_TASK_ID) {
options = ActivityOptions.makeBasic();
@@ -2685,7 +2699,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" --track-allocation: enable tracking of object allocations");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
pw.println(" specified then run as the current user.");
- pw.println(" --stack <STACK_ID>: Specify into which stack should the activity be put.");
+ pw.println(" --windowingMode <WINDOWING_MODE>: The windowing mode to launch the activity into.");
+ pw.println(" --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as.");
pw.println(" start-service [--user <USER_ID> | current] <INTENT>");
pw.println(" Start a Service. Options are:");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 0ccb45f74ec2..49082334db8c 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
@@ -36,7 +35,6 @@ import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.content.Intent.ACTION_MAIN;
@@ -89,10 +87,8 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -1038,7 +1034,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
} else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
activityType = ACTIVITY_TYPE_RECENTS;
- } else if (options != null && options.getLaunchStackId() == ASSISTANT_STACK_ID
+ } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
&& canLaunchAssistActivity(launchedFromPackage)) {
activityType = ACTIVITY_TYPE_ASSISTANT;
}
@@ -1157,8 +1153,15 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
* can be put a secondary screen.
*/
boolean canBeLaunchedOnDisplay(int displayId) {
+ final TaskRecord task = getTask();
+
+ // The resizeability of an Activity's parent task takes precendence over the ActivityInfo.
+ // This allows for a non resizable activity to be launched into a resizeable task.
+ final boolean resizeable =
+ task != null ? task.isResizeable() : supportsResizeableMultiWindow();
+
return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
- supportsResizeableMultiWindow(), launchedFromPid, launchedFromUid, info);
+ resizeable, launchedFromPid, launchedFromUid, info);
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a6a702fbfc13..6140c266f96b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1962,7 +1962,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
boolean isTop) {
final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
- final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing();
+ final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing(
+ mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
final boolean showWhenLocked = r.canShowWhenLocked() && !isInPinnedStack;
final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
@@ -5194,8 +5195,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
voiceInteractor);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, "createTaskRecord");
- final boolean isLockscreenShown =
- mService.mStackSupervisor.mKeyguardController.isKeyguardShowing();
+ final boolean isLockscreenShown = mService.mStackSupervisor.mKeyguardController
+ .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable()
&& !isLockscreenShown) {
task.updateOverrideConfiguration(mBounds);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c8a2a230a7e1..ffe5fd48706a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
@@ -31,13 +32,20 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.getStackIdForActivityType;
+import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
@@ -83,6 +91,7 @@ import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStack.STACK_VISIBLE;
+import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
@@ -94,6 +103,7 @@ import static java.lang.Integer.MAX_VALUE;
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -707,24 +717,26 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
TaskRecord anyTaskForIdLocked(int id) {
- return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
- INVALID_STACK_ID);
+ return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
+ }
+
+ TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode) {
+ return anyTaskForIdLocked(id, matchMode, null);
}
/**
* Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
* @param id Id of the task we would like returned.
* @param matchMode The mode to match the given task id in.
- * @param stackId The stack to restore the task to (default launch stack will be used if
- * stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}). Only
- * valid if the matchMode is
- * {@link #MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE}.
+ * @param aOptions The activity options to use for restoration. Can be null.
*/
- TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode, int stackId) {
+ TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode,
+ @Nullable ActivityOptions aOptions) {
// If there is a stack id set, ensure that we are attempting to actually restore a task
- if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE &&
- stackId != INVALID_STACK_ID) {
- throw new IllegalArgumentException("Should not specify stackId for non-restore lookup");
+ // TODO: Don't really know if this is needed...
+ if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
+ throw new IllegalArgumentException("Should not specify activity options for non-restore"
+ + " lookup");
}
int numDisplays = mActivityDisplays.size();
@@ -762,7 +774,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
// Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
- if (!restoreRecentTaskLocked(task, stackId)) {
+ if (!restoreRecentTaskLocked(task, aOptions)) {
if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
"Couldn't restore task id=" + id + " found in recents");
return null;
@@ -857,8 +869,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
- || anyTaskForIdLocked(candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- INVALID_STACK_ID) != null) {
+ || anyTaskForIdLocked(
+ candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
if (candidateTaskId == currentTaskId) {
// Something wrong!
@@ -2084,38 +2096,35 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// we'll just indicate that this task returns to the home task.
task.setTaskToReturnTo(ACTIVITY_TYPE_HOME);
}
- ActivityStack currentStack = task.getStack();
+ final ActivityStack currentStack = task.getStack();
if (currentStack == null) {
Slog.e(TAG, "findTaskToMoveToFrontLocked: can't move task="
+ task + " to front. Stack is null");
return;
}
- if (task.isResizeable() && options != null) {
- int stackId = options.getLaunchStackId();
- if (canUseActivityOptionsLaunchBounds(options, stackId)) {
- final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
- task.updateOverrideConfiguration(bounds);
- if (stackId == INVALID_STACK_ID) {
- stackId = task.getLaunchStackId();
- }
- if (stackId != currentStack.mStackId) {
- task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
- DEFER_RESUME, "findTaskToMoveToFrontLocked");
- stackId = currentStack.mStackId;
- // moveTaskToStackUncheckedLocked() should already placed the task on top,
- // still need moveTaskToFrontLocked() below for any transition settings.
- }
- if (StackId.resizeStackWithLaunchBounds(stackId)) {
- resizeStackLocked(stackId, bounds,
- null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
- !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME);
- } else {
- // WM resizeTask must be done after the task is moved to the correct stack,
- // because Task's setBounds() also updates dim layer's bounds, but that has
- // dependency on the stack.
- task.resizeWindowContainer();
- }
+ if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {
+ final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
+ task.updateOverrideConfiguration(bounds);
+
+ int stackId = getLaunchStackId(null, options, task);
+
+ if (stackId != currentStack.mStackId) {
+ task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
+ DEFER_RESUME, "findTaskToMoveToFrontLocked");
+ stackId = currentStack.mStackId;
+ // moveTaskToStackUncheckedLocked() should already placed the task on top,
+ // still need moveTaskToFrontLocked() below for any transition settings.
+ }
+ if (StackId.resizeStackWithLaunchBounds(stackId)) {
+ resizeStackLocked(stackId, bounds,
+ null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
+ !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME);
+ } else {
+ // WM resizeTask must be done after the task is moved to the correct stack,
+ // because Task's setBounds() also updates dim layer's bounds, but that has
+ // dependency on the stack.
+ task.resizeWindowContainer();
}
}
@@ -2126,17 +2135,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + currentStack);
- handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY,
+ handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY,
currentStack.mStackId, forceNonResizeable);
}
- boolean canUseActivityOptionsLaunchBounds(ActivityOptions options, int launchStackId) {
+ boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) {
// We use the launch bounds in the activity options is the device supports freeform
// window management or is launching into the pinned stack.
- if (options.getLaunchBounds() == null) {
+ if (options == null || options.getLaunchBounds() == null) {
return false;
}
- return (mService.mSupportsPictureInPicture && launchStackId == PINNED_STACK_ID)
+ return (mService.mSupportsPictureInPicture
+ && options.getLaunchWindowingMode() == WINDOWING_MODE_PINNED)
|| mService.mSupportsFreeformWindowManagement;
}
@@ -2161,6 +2171,179 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return (T) createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
}
+ private int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord task) {
+
+ // First preference if the windowing mode in the activity options if set.
+ int windowingMode = (options != null)
+ ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+
+ // If windowing mode is unset, then next preference is the candidate task, then the
+ // activity record.
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ if (task != null) {
+ windowingMode = task.getWindowingMode();
+ }
+ if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
+ windowingMode = r.getWindowingMode();
+ }
+ }
+
+ // Make sure the windowing mode we are trying to use makes sense for what is supported.
+ if (!mService.mSupportsMultiWindow && windowingMode != WINDOWING_MODE_FULLSCREEN) {
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
+
+ if (!mService.mSupportsSplitScreenMultiWindow
+ && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)) {
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
+
+ if (windowingMode == WINDOWING_MODE_FREEFORM
+ && !mService.mSupportsFreeformWindowManagement) {
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
+
+ return windowingMode;
+ }
+
+ private int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord task) {
+ // First preference if the activity type in the activity options if set.
+ int activityType = (options != null)
+ ? options.getLaunchActivityType() : ACTIVITY_TYPE_UNDEFINED;
+
+ if (activityType != ACTIVITY_TYPE_UNDEFINED) {
+ return activityType;
+ }
+
+ // If activity type is unset, then next preference is the task, then the activity record.
+ if (task != null) {
+ activityType = task.getActivityType();
+ }
+ if (activityType == ACTIVITY_TYPE_UNDEFINED && r != null) {
+ activityType = r.getActivityType();
+ }
+ return activityType;
+ }
+
+ int getLaunchStackId(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord candidateTask) {
+ return getLaunchStackId(r, options, candidateTask, INVALID_DISPLAY);
+ }
+
+ /**
+ * Returns the right stack to use for launching factoring in all the input parameters.
+ *
+ * @param r The activity we are trying to launch. Can be null.
+ * @param options The activity options used to the launch. Can be null.
+ * @param candidateTask The possible task the activity might be launched in. Can be null.
+ *
+ * @return The stack to use for the launch or INVALID_STACK_ID.
+ */
+ int getLaunchStackId(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord candidateTask, int candidateDisplayId) {
+ int taskId = INVALID_TASK_ID;
+ int displayId = INVALID_DISPLAY;
+ //Rect bounds = null;
+
+ // We give preference to the launch preference in activity options.
+ if (options != null) {
+ taskId = options.getLaunchTaskId();
+ displayId = options.getLaunchDisplayId();
+ // TODO: Need to work this into the equation...
+ //bounds = options.getLaunchBounds();
+ }
+
+ // First preference for stack goes to the task Id set in the activity options. Use the stack
+ // associated with that if possible.
+ if (taskId != INVALID_TASK_ID) {
+ // Temporarily set the task id to invalid in case in re-entry.
+ options.setLaunchTaskId(INVALID_TASK_ID);
+ final TaskRecord task = anyTaskForIdLocked(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options);
+ options.setLaunchTaskId(taskId);
+ if (task != null) {
+ return task.getStack().mStackId;
+ }
+ }
+
+ final int windowingMode = resolveWindowingMode(r, options, candidateTask);
+ final int activityType = resolveActivityType(r, options, candidateTask);
+ ActivityStack stack = null;
+
+ // Next preference for stack goes to the display Id set in the activity options or the
+ // candidate display.
+ if (displayId == INVALID_DISPLAY) {
+ displayId = candidateDisplayId;
+ }
+ if (displayId != INVALID_DISPLAY) {
+ if (r != null) {
+ // TODO: This should also take in the windowing mode and activity type into account.
+ stack = getValidLaunchStackOnDisplay(displayId, r);
+ if (stack != null) {
+ return stack.mStackId;
+ }
+ }
+ final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
+ if (display != null) {
+ for (int i = display.mStacks.size() - 1; i >= 0; --i) {
+ stack = display.mStacks.get(i);
+ if (stack.getWindowingMode() == windowingMode
+ && stack.getActivityType() == activityType) {
+ return stack.mStackId;
+ }
+ }
+ // TODO: We should create the stack we want on the display at this point.
+ }
+ }
+
+ // Give preference to the stack and display of the input task and activity if they match the
+ // mode we want to launch into.
+ if (candidateTask != null) {
+ stack = candidateTask.getStack();
+ }
+ if (stack == null && r != null) {
+ stack = r.getStack();
+ }
+ if (stack != null) {
+ if (stack.getWindowingMode() == windowingMode
+ && stack.getActivityType() == activityType) {
+ return stack.mStackId;
+ }
+ ActivityDisplay display = stack.getDisplay();
+
+ if (display != null) {
+ for (int i = display.mStacks.size() - 1; i >= 0; --i) {
+ stack = display.mStacks.get(i);
+ if (stack.getWindowingMode() == windowingMode
+ && stack.getActivityType() == activityType) {
+ return stack.mStackId;
+ }
+ }
+ }
+ }
+
+ // Give preference to the type of activity we are trying to launch followed by the windowing
+ // mode.
+ int stackId = getStackIdForActivityType(activityType);
+ if (stackId != INVALID_STACK_ID) {
+ return stackId;
+ }
+ stackId = getStackIdForWindowingMode(windowingMode);
+ if (stackId != INVALID_STACK_ID) {
+ return stackId;
+ }
+
+ // Whatever...return some default for now.
+ if (candidateTask != null && candidateTask.mBounds != null
+ && mService.mSupportsFreeformWindowManagement) {
+ return FREEFORM_WORKSPACE_STACK_ID;
+ }
+ return FULLSCREEN_WORKSPACE_STACK_ID;
+ }
+
/**
* Get a topmost stack on the display, that is a valid launch stack for specified activity.
* If there is no such stack, new dynamic stack can be created.
@@ -2178,7 +2361,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Return the topmost valid stack on the display.
for (int i = activityDisplay.mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = activityDisplay.mStacks.get(i);
- if (mService.mActivityStarter.isValidLaunchStackId(stack.mStackId, displayId, r)) {
+ if (isValidLaunchStackId(stack.mStackId, displayId, r)) {
return stack;
}
}
@@ -2186,7 +2369,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// If there is no valid stack on the external display - check if new dynamic stack will do.
if (displayId != Display.DEFAULT_DISPLAY) {
final int newDynamicStackId = getNextStackId();
- if (mService.mActivityStarter.isValidLaunchStackId(newDynamicStackId, displayId, r)) {
+ if (isValidLaunchStackId(newDynamicStackId, displayId, r)) {
return createStackOnDisplay(newDynamicStackId, displayId, true /*onTop*/);
}
}
@@ -2195,6 +2378,32 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return null;
}
+ boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
+ switch (stackId) {
+ case INVALID_STACK_ID:
+ case HOME_STACK_ID:
+ return false;
+ case FULLSCREEN_WORKSPACE_STACK_ID:
+ return true;
+ case FREEFORM_WORKSPACE_STACK_ID:
+ return r.supportsFreeform();
+ case DOCKED_STACK_ID:
+ return r.supportsSplitScreen();
+ case PINNED_STACK_ID:
+ return r.supportsPictureInPicture();
+ case RECENTS_STACK_ID:
+ return r.isActivityTypeRecents();
+ case ASSISTANT_STACK_ID:
+ return r.isActivityTypeAssistant();
+ default:
+ if (StackId.isDynamicStack(stackId)) {
+ return r.canBeLaunchedOnDisplay(displayId);
+ }
+ Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
+ return false;
+ }
+ }
+
ArrayList<ActivityStack> getStacks() {
ArrayList<ActivityStack> allStacks = new ArrayList<>();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
@@ -2345,8 +2554,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
continueUpdateBounds(RECENTS_STACK_ID);
for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) {
final int taskId = mResizingTasksDuringAnimation.valueAt(i);
- final TaskRecord task =
- anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
+ final TaskRecord task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY);
if (task != null) {
task.setTaskDockedResizing(false);
}
@@ -2641,8 +2849,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
*/
boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
boolean pauseImmediately) {
- final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- INVALID_STACK_ID);
+ final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
tr.removeTaskActivitiesLocked(pauseImmediately);
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
@@ -2741,23 +2948,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
/**
* Restores a recent task to a stack
* @param task The recent task to be restored.
- * @param stackId The stack to restore the task to (default launch stack will be used
- * if stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}
- * or is not a static stack).
+ * @param aOptions The activity options to use for restoration.
* @return true if the task has been restored successfully.
*/
- boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
- if (!StackId.isStaticStack(stackId)) {
- // If stack is not static (or stack id is invalid) - use the default one.
- // This means that tasks that were on external displays will be restored on the
- // primary display.
- stackId = task.getLaunchStackId();
- } else if (stackId == DOCKED_STACK_ID && !task.supportsSplitScreen()) {
- // Preferred stack is the docked stack, but the task can't go in the docked stack.
- // Put it in the fullscreen stack.
- stackId = FULLSCREEN_WORKSPACE_STACK_ID;
- }
-
+ boolean restoreRecentTaskLocked(TaskRecord task, ActivityOptions aOptions) {
+ final int stackId = getLaunchStackId(null, aOptions, task);
final ActivityStack currentStack = task.getStack();
if (currentStack != null) {
// Task has already been restored once. See if we need to do anything more
@@ -2770,15 +2965,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
}
- final ActivityStack stack =
- getStack(stackId, CREATE_IF_NEEDED, !ON_TOP);
-
- if (stack == null) {
- // What does this mean??? Not sure how we would get here...
- if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
- "Unable to find/create stack to restore recent task=" + task);
- return false;
- }
+ final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, !ON_TOP);
stack.addTask(task, false /* toTop */, "restoreRecentTask");
// TODO: move call for creation here and other place into Stack.addTask()
@@ -4015,21 +4202,20 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return list;
}
- void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId,
+ void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
int preferredDisplayId, int actualStackId) {
- handleNonResizableTaskIfNeeded(task, preferredStackId, preferredDisplayId, actualStackId,
- false /* forceNonResizable */);
+ handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
+ actualStackId, false /* forceNonResizable */);
}
- void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId,
+ void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
int preferredDisplayId, int actualStackId, boolean forceNonResizable) {
final boolean isSecondaryDisplayPreferred =
- (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY)
- || StackId.isDynamicStack(preferredStackId);
+ (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
final ActivityStack actualStack = getStack(actualStackId);
final boolean inSplitScreenMode = actualStack != null
&& actualStack.inSplitScreenWindowingMode();
- if (((!inSplitScreenMode && preferredStackId != DOCKED_STACK_ID)
+ if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
&& !isSecondaryDisplayPreferred) || task.isActivityTypeHome()) {
return;
}
@@ -4424,18 +4610,22 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final String callingPackage;
final Intent intent;
final int userId;
+ int activityType = ACTIVITY_TYPE_UNDEFINED;
+ int windowingMode = WINDOWING_MODE_UNDEFINED;
final ActivityOptions activityOptions = (bOptions != null)
? new ActivityOptions(bOptions) : null;
- final int launchStackId = (activityOptions != null)
- ? activityOptions.getLaunchStackId() : INVALID_STACK_ID;
- if (StackId.isHomeOrRecentsStack(launchStackId)) {
+ if (activityOptions != null) {
+ activityType = activityOptions.getLaunchActivityType();
+ windowingMode = activityOptions.getLaunchWindowingMode();
+ }
+ if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
throw new IllegalArgumentException("startActivityFromRecentsInner: Task "
+ taskId + " can't be launch in the home/recents stack.");
}
mWindowManager.deferSurfaceLayout();
try {
- if (launchStackId == DOCKED_STACK_ID) {
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mWindowManager.setDockedStackCreateState(
activityOptions.getDockCreateMode(), null /* initialBounds */);
@@ -4447,7 +4637,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
- launchStackId);
+ activityOptions);
if (task == null) {
continueUpdateBounds(RECENTS_STACK_ID);
mWindowManager.executeAppTransition();
@@ -4458,14 +4648,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Since we don't have an actual source record here, we assume that the currently
// focused activity was the source.
final ActivityStack focusedStack = getFocusedStack();
- final ActivityRecord sourceRecord =
- focusedStack != null ? focusedStack.topActivity() : null;
+ final ActivityRecord sourceRecord = focusedStack != null
+ ? focusedStack.topActivity() : null;
+ final int stackId = getLaunchStackId(null, activityOptions, task);
- if (launchStackId != INVALID_STACK_ID) {
- if (task.getStackId() != launchStackId) {
- task.reparent(launchStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE,
- DEFER_RESUME, "startActivityFromRecents");
- }
+ if (stackId != INVALID_STACK_ID && task.getStackId() != stackId) {
+ task.reparent(stackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
+ "startActivityFromRecents");
}
// If the user must confirm credentials (e.g. when first launching a work app and the
@@ -4484,7 +4673,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// If we are launching the task in the docked stack, put it into resizing mode so
// the window renders full-screen with the background filling the void. Also only
// call this at the end to make sure that tasks exists on the window manager side.
- if (launchStackId == DOCKED_STACK_ID) {
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
setResizingDuringAnimation(task);
}
@@ -4502,7 +4691,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
userId = task.userId;
int result = mService.startActivityInPackage(callingUid, callingPackage, intent, null,
null, null, 0, 0, bOptions, userId, task, "startActivityFromRecents");
- if (launchStackId == DOCKED_STACK_ID) {
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
setResizingDuringAnimation(task);
}
return result;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 16abcfb620d9..d94e866b312b 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -39,6 +39,8 @@ import static android.app.ActivityManager.StackId.isDynamicStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -1024,10 +1026,12 @@ class ActivityStarter {
ActivityRecord reusedActivity = getReusableIntentActivity();
- final int preferredLaunchStackId =
- (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
- final int preferredLaunchDisplayId =
- (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
+ int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
+ int preferredLaunchDisplayId = DEFAULT_DISPLAY;
+ if (mOptions != null) {
+ preferredWindowingMode = mOptions.getLaunchWindowingMode();
+ preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
+ }
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
@@ -1158,7 +1162,7 @@ class ActivityStarter {
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
- mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
+ mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
@@ -1173,8 +1177,7 @@ class ActivityStarter {
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
- result = setTaskFromReuseOrCreateNewTask(
- taskToAffiliate, preferredLaunchStackId, topStack);
+ result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
@@ -1241,7 +1244,7 @@ class ActivityStarter {
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
- mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
+ mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
@@ -1654,8 +1657,8 @@ class ActivityStarter {
mTargetStack.moveToFront("intentActivityFound");
}
- mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
- DEFAULT_DISPLAY, mTargetStack.mStackId);
+ mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
+ WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId);
// If the caller has requested that the target task be reset, then do so.
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
@@ -1675,8 +1678,7 @@ class ActivityStarter {
// Task will be launched over the home stack, so return home.
task.setTaskToReturnTo(ACTIVITY_TYPE_HOME);
return;
- } else if (focusedStack != null && focusedStack != task.getStack() &&
- focusedStack.isActivityTypeAssistant()) {
+ } else if (focusedStack != task.getStack() && focusedStack.isActivityTypeAssistant()) {
// Task was launched over the assistant stack, so return there
task.setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT);
return;
@@ -1779,7 +1781,7 @@ class ActivityStarter {
}
private int setTaskFromReuseOrCreateNewTask(
- TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
+ TaskRecord taskToAffiliate, ActivityStack topStack) {
mTargetStack = computeStackFocus(
mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
@@ -1821,8 +1823,10 @@ class ActivityStarter {
// If stack id is specified in activity options, usually it means that activity is
// launched not from currently focused stack (e.g. from SysUI or from shell) - in
// that case we check the target stack.
+ // TODO: Not sure I understand the value or use of the commented out code and the
+ // comment above. See if this causes any issues and why...
updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
- preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
+ /*preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : */topStack);
}
if (mDoResume) {
mTargetStack.moveToFront("reuseOrNewTask");
@@ -1964,7 +1968,8 @@ class ActivityStarter {
if (mLaunchBounds != null) {
mInTask.updateOverrideConfiguration(mLaunchBounds);
- int stackId = mInTask.getLaunchStackId();
+ // TODO: Shouldn't we already know what stack to use by the time we get here?
+ int stackId = mSupervisor.getLaunchStackId(null, null, mInTask);
if (stackId != mInTask.getStackId()) {
mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
DEFER_RESUME, "inTaskToFront");
@@ -2102,9 +2107,10 @@ class ActivityStarter {
}
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
- final int stackId = task != null ? task.getLaunchStackId() :
- bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
- FULLSCREEN_WORKSPACE_STACK_ID;
+ final int stackId = task != null ? mSupervisor.getLaunchStackId(r, aOptions, task)
+ // TODO: This should go in mSupervisor.getLaunchStackId method...
+ : bounds != null && mService.mSupportsFreeformWindowManagement
+ ? FREEFORM_WORKSPACE_STACK_ID : FULLSCREEN_WORKSPACE_STACK_ID;
stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
@@ -2165,18 +2171,16 @@ class ActivityStarter {
return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
- final int launchDisplayId =
- (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
-
- final int launchStackId =
- (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
-
- if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
- throw new IllegalArgumentException(
- "Stack and display id can't be set at the same time.");
+ int launchDisplayId = INVALID_DISPLAY;
+ int launchStackId = INVALID_STACK_ID;
+ if (aOptions != null) {
+ launchDisplayId = aOptions.getLaunchDisplayId();
+ final int vrDisplayId = mUsingVr2dDisplay ? mSourceDisplayId : INVALID_DISPLAY;
+ launchStackId = mSupervisor.getLaunchStackId(r, aOptions, task, vrDisplayId);
}
- if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
+ // TODO: Will no longer be needed once we are on longer using static stack ids.
+ if (mSupervisor.isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
}
if (launchStackId == DOCKED_STACK_ID) {
@@ -2184,12 +2188,14 @@ class ActivityStarter {
// for this activity, so we put the activity in the fullscreen stack.
return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
+ // TODO: Can probably be removed since ASS.getLaunchStackId() does display resolution.
if (launchDisplayId != INVALID_DISPLAY) {
// Stack id has higher priority than display id.
return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
}
// If we are using Vr2d display, find the virtual display stack.
+ // TODO: Can be removed.
if (mUsingVr2dDisplay) {
ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
if (DEBUG_STACK) {
@@ -2240,39 +2246,11 @@ class ActivityStarter {
}
}
- boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
- switch (stackId) {
- case INVALID_STACK_ID:
- case HOME_STACK_ID:
- return false;
- case FULLSCREEN_WORKSPACE_STACK_ID:
- return true;
- case FREEFORM_WORKSPACE_STACK_ID:
- return r.supportsFreeform();
- case DOCKED_STACK_ID:
- return r.supportsSplitScreen();
- case PINNED_STACK_ID:
- return r.supportsPictureInPicture();
- case RECENTS_STACK_ID:
- return r.isActivityTypeRecents();
- case ASSISTANT_STACK_ID:
- return r.isActivityTypeAssistant();
- default:
- if (StackId.isDynamicStack(stackId)) {
- return r.canBeLaunchedOnDisplay(displayId);
- }
- Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
- return false;
- }
- }
-
- Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
+ private Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
Rect newBounds = null;
- if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
- if (mSupervisor.canUseActivityOptionsLaunchBounds(
- options, options.getLaunchStackId())) {
- newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
- }
+ if (mSupervisor.canUseActivityOptionsLaunchBounds(options)
+ && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
+ newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
}
return newBounds;
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index cea80c8d0e9d..85961135d84f 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -19,6 +19,7 @@ package com.android.server.am;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
@@ -66,6 +67,7 @@ class KeyguardController {
private int mBeforeUnoccludeTransit;
private int mVisibilityTransactionDepth;
private SleepToken mSleepToken;
+ private int mSecondaryDisplayShowing = INVALID_DISPLAY;
KeyguardController(ActivityManagerService service,
ActivityStackSupervisor stackSupervisor) {
@@ -78,10 +80,12 @@ class KeyguardController {
}
/**
- * @return true if Keyguard is showing, not going away, and not being occluded, false otherwise
+ * @return true if Keyguard is showing, not going away, and not being occluded on the given
+ * display, false otherwise
*/
- boolean isKeyguardShowing() {
- return mKeyguardShowing && !mKeyguardGoingAway && !mOccluded;
+ boolean isKeyguardShowing(int displayId) {
+ return mKeyguardShowing && !mKeyguardGoingAway &&
+ (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
}
/**
@@ -94,15 +98,19 @@ class KeyguardController {
/**
* Update the Keyguard showing state.
*/
- void setKeyguardShown(boolean showing) {
- if (showing == mKeyguardShowing) {
+ void setKeyguardShown(boolean showing, int secondaryDisplayShowing) {
+ boolean showingChanged = showing != mKeyguardShowing;
+ if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
return;
}
mKeyguardShowing = showing;
- dismissDockedStackIfNeeded();
- if (showing) {
- setKeyguardGoingAway(false);
- mDismissalRequested = false;
+ mSecondaryDisplayShowing = secondaryDisplayShowing;
+ if (showingChanged) {
+ dismissDockedStackIfNeeded();
+ if (showing) {
+ setKeyguardGoingAway(false);
+ mDismissalRequested = false;
+ }
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
updateKeyguardSleepToken();
@@ -337,9 +345,9 @@ class KeyguardController {
}
private void updateKeyguardSleepToken() {
- if (mSleepToken == null && isKeyguardShowing()) {
+ if (mSleepToken == null && isKeyguardShowing(DEFAULT_DISPLAY)) {
mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY);
- } else if (mSleepToken != null && !isKeyguardShowing()) {
+ } else if (mSleepToken != null && !isKeyguardShowing(DEFAULT_DISPLAY)) {
mSleepToken.release();
mSleepToken = null;
}
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 241e58391144..72b5de88e50f 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -25,6 +25,7 @@ import static android.app.StatusBarManager.DISABLE_HOME;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.StatusBarManager.DISABLE_RECENT;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
import static android.os.UserHandle.USER_ALL;
@@ -431,8 +432,8 @@ public class LockTaskController {
mSupervisor.resumeFocusedStackTopActivityLocked();
mWindowManager.executeAppTransition();
} else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
- mSupervisor.handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY,
- task.getStackId(), true /* forceNonResizable */);
+ mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
+ DEFAULT_DISPLAY, task.getStackId(), true /* forceNonResizable */);
}
}
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 74c4826f583b..f6e20cd2e1b4 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -472,8 +472,7 @@ public class TaskPersister {
final int taskId = task.taskId;
if (mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- INVALID_STACK_ID) != null) {
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
// Should not happen.
Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
} else if (userId != task.userId) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 48da6555e75c..28b71d9c978d 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -26,6 +26,7 @@ import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -507,8 +508,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
updateOverrideConfiguration(bounds);
if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
// re-restore the task so it can have the proper stack association.
- mService.mStackSupervisor.restoreRecentTaskLocked(this,
- FREEFORM_WORKSPACE_STACK_ID);
+ mService.mStackSupervisor.restoreRecentTaskLocked(this, null);
}
return true;
}
@@ -729,7 +729,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
// TODO: Handle incorrect request to move before the actual move, not after.
- supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, DEFAULT_DISPLAY, stackId);
+ supervisor.handleNonResizableTaskIfNeeded(this, getWindowingModeForStackId(preferredStackId,
+ supervisor.getStack(DOCKED_STACK_ID) != null), DEFAULT_DISPLAY, stackId);
boolean successful = (preferredStackId == stackId);
if (successful && stackId == DOCKED_STACK_ID) {
@@ -2079,27 +2080,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
}
- /**
- * Returns the correct stack to use based on task type and currently set bounds,
- * regardless of the focused stack and current stack association of the task.
- * The task will be moved (and stack focus changed) later if necessary.
- */
- int getLaunchStackId() {
- if (isActivityTypeRecents()) {
- return RECENTS_STACK_ID;
- }
- if (isActivityTypeHome()) {
- return HOME_STACK_ID;
- }
- if (isActivityTypeAssistant()) {
- return ASSISTANT_STACK_ID;
- }
- if (mBounds != null) {
- return FREEFORM_WORKSPACE_STACK_ID;
- }
- return FULLSCREEN_WORKSPACE_STACK_ID;
- }
-
/** Returns the bounds that should be used to launch this task. */
private Rect getLaunchBounds() {
if (mStack == null) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index db6bb7d8e653..f2e294217999 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -22,6 +22,7 @@ import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM;
import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
import static android.app.ActivityManager.USER_OP_IS_CURRENT;
import static android.app.ActivityManager.USER_OP_SUCCESS;
+import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
@@ -30,14 +31,6 @@ import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY;
import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL;
import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE;
import static com.android.server.am.ActivityManagerService.MY_PID;
-import static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG;
-import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG;
-import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG;
-import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG;
-import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG;
-import static com.android.server.am.ActivityManagerService.SYSTEM_USER_UNLOCK_MSG;
-import static com.android.server.am.ActivityManagerService.USER_SWITCH_CALLBACKS_TIMEOUT_MSG;
-import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG;
import static com.android.server.am.UserState.STATE_BOOTING;
import static com.android.server.am.UserState.STATE_RUNNING_LOCKED;
import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKED;
@@ -68,6 +61,7 @@ import android.os.IBinder;
import android.os.IProgressListener;
import android.os.IRemoteCallback;
import android.os.IUserManager;
+import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -78,6 +72,7 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
+import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Pair;
@@ -93,6 +88,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
+import com.android.server.SystemServiceManager;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
@@ -108,7 +104,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
*/
-class UserController {
+class UserController implements Handler.Callback {
private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM;
// Maximum number of users we allow to be running at a time.
@@ -118,6 +114,23 @@ class UserController {
// giving up on them and unfreezing the screen.
static final int USER_SWITCH_TIMEOUT_MS = 3 * 1000;
+ // ActivityManager thread message constants
+ static final int REPORT_USER_SWITCH_MSG = 10;
+ static final int CONTINUE_USER_SWITCH_MSG = 20;
+ static final int USER_SWITCH_TIMEOUT_MSG = 30;
+ static final int START_PROFILES_MSG = 40;
+ static final int SYSTEM_USER_START_MSG = 50;
+ static final int SYSTEM_USER_CURRENT_MSG = 60;
+ static final int FOREGROUND_PROFILE_CHANGED_MSG = 70;
+ static final int REPORT_USER_SWITCH_COMPLETE_MSG = 80;
+ static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 90;
+ static final int SYSTEM_USER_UNLOCK_MSG = 100;
+ static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
+ static final int START_USER_SWITCH_FG_MSG = 120;
+
+ // UI thread message constants
+ static final int START_USER_SWITCH_UI_MSG = 1000;
+
// If a callback wasn't called within USER_SWITCH_CALLBACKS_TIMEOUT_MS after
// USER_SWITCH_TIMEOUT_MS, an error is reported. Usually it indicates a problem in the observer
// when it never calls back.
@@ -126,6 +139,7 @@ class UserController {
private final Object mLock;
private final Injector mInjector;
private final Handler mHandler;
+ private final Handler mUiHandler;
// Holds the current foreground user's id. Use mLock when updating
@GuardedBy("mLock")
@@ -193,7 +207,8 @@ class UserController {
UserController(Injector injector) {
mInjector = injector;
mLock = injector.getLock();
- mHandler = injector.getHandler();
+ mHandler = mInjector.getHandler(this);
+ mUiHandler = mInjector.getUiHandler(this);
// User 0 is the first and only user that runs at boot.
final UserState uss = new UserState(UserHandle.SYSTEM);
mStartedUsers.put(UserHandle.USER_SYSTEM, uss);
@@ -499,7 +514,7 @@ class UserController {
if (userId < 0 || userId == UserHandle.USER_SYSTEM) {
throw new IllegalArgumentException("Can't stop system user " + userId);
}
- mInjector.enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
synchronized (mLock) {
return stopUsersLocked(userId, force, callback);
}
@@ -635,7 +650,7 @@ class UserController {
mInjector.batteryStatsServiceNoteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
Integer.toString(userId), userId);
- mInjector.systemServiceManagerStopUser(userId);
+ mInjector.getSystemServiceManager().stopUser(userId);
synchronized (mLock) {
mInjector.broadcastIntentLocked(shutdownIntent,
@@ -765,6 +780,13 @@ class UserController {
}
}
+ void scheduleStartProfilesLocked() {
+ if (!mHandler.hasMessages(START_PROFILES_MSG)) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
+ DateUtils.SECOND_IN_MILLIS);
+ }
+ }
+
void startProfilesLocked() {
if (DEBUG_MU) Slog.i(TAG, "startProfilesLocked");
List<UserInfo> profiles = mInjector.getUserManager().getProfiles(
@@ -1080,6 +1102,50 @@ class UserController {
return true;
}
+ boolean switchUser(final int targetUserId) {
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId);
+ int currentUserId;
+ UserInfo targetUserInfo;
+ synchronized (mLock) {
+ currentUserId = getCurrentUserIdLocked();
+ targetUserInfo = getUserInfo(targetUserId);
+ if (targetUserId == currentUserId) {
+ Slog.i(TAG, "user #" + targetUserId + " is already the current user");
+ return true;
+ }
+ if (targetUserInfo == null) {
+ Slog.w(TAG, "No user info for user #" + targetUserId);
+ return false;
+ }
+ if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mInjector.getContext())) {
+ Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId
+ + " when device is in demo mode");
+ return false;
+ }
+ if (!targetUserInfo.supportsSwitchTo()) {
+ Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
+ return false;
+ }
+ if (targetUserInfo.isManagedProfile()) {
+ Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
+ return false;
+ }
+ setTargetUserIdLocked(targetUserId);
+ }
+ if (mUserSwitchUiEnabled) {
+ UserInfo currentUserInfo = getUserInfo(currentUserId);
+ Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo);
+ mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG);
+ mUiHandler.sendMessage(mHandler.obtainMessage(
+ START_USER_SWITCH_UI_MSG, userNames));
+ } else {
+ mHandler.removeMessages(START_USER_SWITCH_FG_MSG);
+ mHandler.sendMessage(mHandler.obtainMessage(
+ START_USER_SWITCH_FG_MSG, targetUserId, 0));
+ }
+ return true;
+ }
+
void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) {
// The dialog will show and then initiate the user switch by calling startUserInForeground
mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second);
@@ -1215,7 +1281,7 @@ class UserController {
void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) {
mCurWaitingUserSwitchCallbacks = null;
mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(ActivityManagerService.CONTINUE_USER_SWITCH_MSG,
+ mHandler.sendMessage(mHandler.obtainMessage(CONTINUE_USER_SWITCH_MSG,
oldUserId, newUserId, uss));
}
@@ -1395,6 +1461,11 @@ class UserController {
mUserSwitchObservers.register(observer, name);
}
+ void sendForegroundProfileChanged(int userId) {
+ mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
+ mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG, userId, 0).sendToTarget();
+ }
+
void unregisterUserSwitchObserver(IUserSwitchObserver observer) {
mUserSwitchObservers.unregister(observer);
}
@@ -1575,6 +1646,15 @@ class UserController {
return mInjector.getUserManager().exists(userId);
}
+ void enforceShellRestriction(String restriction, int userHandle) {
+ if (Binder.getCallingUid() == SHELL_UID) {
+ if (userHandle < 0 || hasUserRestriction(restriction, userHandle)) {
+ throw new SecurityException("Shell does not have permission to access user "
+ + userHandle);
+ }
+ }
+ }
+
boolean hasUserRestriction(String restriction, int userId) {
return mInjector.getUserManager().hasUserRestriction(restriction, userId);
}
@@ -1667,6 +1747,72 @@ class UserController {
}
}
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case START_USER_SWITCH_FG_MSG:
+ startUserInForeground(msg.arg1);
+ break;
+ case REPORT_USER_SWITCH_MSG:
+ dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
+ break;
+ case CONTINUE_USER_SWITCH_MSG:
+ continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
+ break;
+ case USER_SWITCH_TIMEOUT_MSG:
+ timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
+ break;
+ case USER_SWITCH_CALLBACKS_TIMEOUT_MSG:
+ timeoutUserSwitchCallbacks(msg.arg1, msg.arg2);
+ break;
+ case START_PROFILES_MSG:
+ synchronized (mLock) {
+ startProfilesLocked();
+ }
+ break;
+ case SYSTEM_USER_START_MSG:
+ mInjector.batteryStatsServiceNoteEvent(
+ BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
+ Integer.toString(msg.arg1), msg.arg1);
+ mInjector.getSystemServiceManager().startUser(msg.arg1);
+ break;
+ case SYSTEM_USER_UNLOCK_MSG:
+ final int userId = msg.arg1;
+ mInjector.getSystemServiceManager().unlockUser(userId);
+ synchronized (mLock) {
+ mInjector.loadUserRecentsLocked(userId);
+ }
+ if (userId == UserHandle.USER_SYSTEM) {
+ mInjector.startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ }
+ mInjector.installEncryptionUnawareProviders(userId);
+ finishUserUnlocked((UserState) msg.obj);
+ break;
+ case SYSTEM_USER_CURRENT_MSG:
+ mInjector.batteryStatsServiceNoteEvent(
+ BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
+ Integer.toString(msg.arg2), msg.arg2);
+ mInjector.batteryStatsServiceNoteEvent(
+ BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
+ Integer.toString(msg.arg1), msg.arg1);
+
+ mInjector.getSystemServiceManager().switchUser(msg.arg1);
+ break;
+ case FOREGROUND_PROFILE_CHANGED_MSG:
+ dispatchForegroundProfileChanged(msg.arg1);
+ break;
+ case REPORT_USER_SWITCH_COMPLETE_MSG:
+ dispatchUserSwitchComplete(msg.arg1);
+ break;
+ case REPORT_LOCKED_BOOT_COMPLETE_MSG:
+ dispatchLockedBootComplete(msg.arg1);
+ break;
+ case START_USER_SWITCH_UI_MSG:
+ showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj);
+ break;
+ }
+ return false;
+ }
+
@VisibleForTesting
static class Injector {
private final ActivityManagerService mService;
@@ -1681,8 +1827,12 @@ class UserController {
return mService;
}
- protected Handler getHandler() {
- return mService.mHandler;
+ protected Handler getHandler(Handler.Callback callback) {
+ return new Handler(mService.mHandlerThread.getLooper(), callback);
+ }
+
+ protected Handler getUiHandler(Handler.Callback callback) {
+ return new Handler(mService.mUiHandler.getLooper(), callback);
}
protected Context getContext() {
@@ -1740,14 +1890,14 @@ class UserController {
mService.mBatteryStatsService.noteEvent(code, name, uid);
}
- void systemServiceManagerStopUser(int userId) {
- mService.mSystemServiceManager.stopUser(userId);
- }
-
boolean isRuntimeRestarted() {
return mService.mSystemServiceManager.isRuntimeRestarted();
}
+ SystemServiceManager getSystemServiceManager() {
+ return mService.mSystemServiceManager;
+ }
+
boolean isFirstBootOrUpgrade() {
IPackageManager pm = AppGlobals.getPackageManager();
try {
@@ -1788,8 +1938,16 @@ class UserController {
mService.clearBroadcastQueueForUserLocked(userId);
}
- void enforceShellRestriction(String restriction, int userId) {
- mService.enforceShellRestriction(restriction, userId);
+ void loadUserRecentsLocked(int userId) {
+ mService.mRecentTasks.loadUserRecentsLocked(userId);
+ }
+
+ void startPersistentApps(int matchFlags) {
+ mService.startPersistentApps(matchFlags);
+ }
+
+ void installEncryptionUnawareProviders(int userId) {
+ mService.installEncryptionUnawareProviders(userId);
}
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 91b15912fcb5..11d0470ee8e5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6134,12 +6134,12 @@ public class AudioService extends IAudioService.Stub
private int mSafeMediaVolumeIndex;
// mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
// corresponding to a gain of -30 dBFS in audio flinger mixer.
- // We remove -15 dBs from the theoretical -15dB to account for the EQ boost when bands are set
- // to max gain.
+ // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
+ // amplification when both effects are on with all band gains at maximum.
// This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
// the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
private int mSafeUsbMediaVolumeIndex;
- private static final float SAFE_VOLUME_GAIN_DBFS = -30.0f;
+ private static final float SAFE_VOLUME_GAIN_DBFS = -37.0f;
// mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index 22330e66e126..67e72167faa7 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -126,7 +126,7 @@ final public class IpConnectivityEventBuilder {
wakeupStats.systemWakeups = in.systemWakeups;
wakeupStats.nonApplicationWakeups = in.nonApplicationWakeups;
wakeupStats.applicationWakeups = in.applicationWakeups;
- wakeupStats.unroutedWakeups = in.unroutedWakeups;
+ wakeupStats.noUidWakeups = in.noUidWakeups;
final IpConnectivityEvent out = buildEvent(0, 0, in.iface);
out.setWakeupStats(wakeupStats);
return out;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 6f7ace2f6527..25dba3570e20 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -170,11 +170,11 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
timestampMs = System.currentTimeMillis();
}
- addWakupEvent(iface, timestampMs, uid);
+ addWakeupEvent(iface, timestampMs, uid);
}
@GuardedBy("this")
- private void addWakupEvent(String iface, long timestampMs, int uid) {
+ private void addWakeupEvent(String iface, long timestampMs, int uid) {
int index = wakeupEventIndex(mWakeupEventCursor);
mWakeupEventCursor++;
WakeupEvent event = new WakeupEvent();
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index aafc6317bfae..9cf136720881 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -48,8 +48,10 @@ import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.Calendar;
import java.util.TimeZone;
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
@@ -306,7 +308,7 @@ public final class NightDisplayService extends SystemService
}
@Override
- public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+ public void onCustomStartTimeChanged(LocalTime startTime) {
Slog.d(TAG, "onCustomStartTimeChanged: startTime=" + startTime);
if (mAutoMode != null) {
@@ -315,7 +317,7 @@ public final class NightDisplayService extends SystemService
}
@Override
- public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+ public void onCustomEndTimeChanged(LocalTime endTime) {
Slog.d(TAG, "onCustomEndTimeChanged: endTime=" + endTime);
if (mAutoMode != null) {
@@ -414,6 +416,36 @@ public final class NightDisplayService extends SystemService
outTemp[10] = blue;
}
+ /**
+ * Returns the first date time corresponding to the local time that occurs before the
+ * provided date time.
+ *
+ * @param compareTime the LocalDateTime to compare against
+ * @return the prior LocalDateTime corresponding to this local time
+ */
+ public static LocalDateTime getDateTimeBefore(LocalTime localTime, LocalDateTime compareTime) {
+ final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(),
+ compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute());
+
+ // Check if the local time has passed, if so return the same time yesterday.
+ return ldt.isAfter(compareTime) ? ldt.minusDays(1) : ldt;
+ }
+
+ /**
+ * Returns the first date time corresponding to this local time that occurs after the
+ * provided date time.
+ *
+ * @param compareTime the LocalDateTime to compare against
+ * @return the next LocalDateTime corresponding to this local time
+ */
+ public static LocalDateTime getDateTimeAfter(LocalTime localTime, LocalDateTime compareTime) {
+ final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(),
+ compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute());
+
+ // Check if the local time has passed, if so return the same time tomorrow.
+ return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt;
+ }
+
private abstract class AutoMode implements NightDisplayController.Callback {
public abstract void onStart();
@@ -425,10 +457,10 @@ public final class NightDisplayService extends SystemService
private final AlarmManager mAlarmManager;
private final BroadcastReceiver mTimeChangedReceiver;
- private NightDisplayController.LocalTime mStartTime;
- private NightDisplayController.LocalTime mEndTime;
+ private LocalTime mStartTime;
+ private LocalTime mEndTime;
- private Calendar mLastActivatedTime;
+ private LocalDateTime mLastActivatedTime;
CustomAutoMode() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
@@ -441,31 +473,15 @@ public final class NightDisplayService extends SystemService
}
private void updateActivated() {
- final Calendar now = Calendar.getInstance();
- final Calendar startTime = mStartTime.getDateTimeBefore(now);
- final Calendar endTime = mEndTime.getDateTimeAfter(startTime);
+ final LocalDateTime now = LocalDateTime.now();
+ final LocalDateTime start = getDateTimeBefore(mStartTime, now);
+ final LocalDateTime end = getDateTimeAfter(mEndTime, start);
+ boolean activate = now.isBefore(end);
- boolean activate = now.before(endTime);
if (mLastActivatedTime != null) {
- // Convert mLastActivatedTime to the current timezone if needed.
- final TimeZone currentTimeZone = now.getTimeZone();
- if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
- final int year = mLastActivatedTime.get(Calendar.YEAR);
- final int dayOfYear = mLastActivatedTime.get(Calendar.DAY_OF_YEAR);
- final int hourOfDay = mLastActivatedTime.get(Calendar.HOUR_OF_DAY);
- final int minute = mLastActivatedTime.get(Calendar.MINUTE);
-
- mLastActivatedTime.setTimeZone(currentTimeZone);
- mLastActivatedTime.set(Calendar.YEAR, year);
- mLastActivatedTime.set(Calendar.DAY_OF_YEAR, dayOfYear);
- mLastActivatedTime.set(Calendar.HOUR_OF_DAY, hourOfDay);
- mLastActivatedTime.set(Calendar.MINUTE, minute);
- }
-
// Maintain the existing activated state if within the current period.
- if (mLastActivatedTime.before(now)
- && mLastActivatedTime.after(startTime)
- && (mLastActivatedTime.after(endTime) || now.before(endTime))) {
+ if (mLastActivatedTime.isBefore(now) && mLastActivatedTime.isAfter(start)
+ && (mLastActivatedTime.isAfter(end) || now.isBefore(end))) {
activate = mController.isActivated();
}
}
@@ -473,14 +489,16 @@ public final class NightDisplayService extends SystemService
if (mIsActivated == null || mIsActivated != activate) {
mController.setActivated(activate);
}
+
updateNextAlarm(mIsActivated, now);
}
- private void updateNextAlarm(@Nullable Boolean activated, @NonNull Calendar now) {
+ private void updateNextAlarm(@Nullable Boolean activated, @NonNull LocalDateTime now) {
if (activated != null) {
- final Calendar next = activated ? mEndTime.getDateTimeAfter(now)
- : mStartTime.getDateTimeAfter(now);
- mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null);
+ final LocalDateTime next = activated ? getDateTimeAfter(mEndTime, now)
+ : getDateTimeAfter(mStartTime, now);
+ final long millis = next.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+ mAlarmManager.setExact(AlarmManager.RTC, millis, TAG, this, null);
}
}
@@ -510,18 +528,18 @@ public final class NightDisplayService extends SystemService
@Override
public void onActivated(boolean activated) {
mLastActivatedTime = mController.getLastActivatedTime();
- updateNextAlarm(activated, Calendar.getInstance());
+ updateNextAlarm(activated, LocalDateTime.now());
}
@Override
- public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+ public void onCustomStartTimeChanged(LocalTime startTime) {
mStartTime = startTime;
mLastActivatedTime = null;
updateActivated();
}
@Override
- public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+ public void onCustomEndTimeChanged(LocalTime endTime) {
mEndTime = endTime;
mLastActivatedTime = null;
updateActivated();
@@ -550,15 +568,14 @@ public final class NightDisplayService extends SystemService
}
boolean activate = state.isNight();
- final Calendar lastActivatedTime = mController.getLastActivatedTime();
+ final LocalDateTime lastActivatedTime = mController.getLastActivatedTime();
if (lastActivatedTime != null) {
- final Calendar now = Calendar.getInstance();
- final Calendar sunrise = state.sunrise();
- final Calendar sunset = state.sunset();
-
+ final LocalDateTime now = LocalDateTime.now();
+ final LocalDateTime sunrise = state.sunrise();
+ final LocalDateTime sunset = state.sunset();
// Maintain the existing activated state if within the current period.
- if (lastActivatedTime.before(now)
- && (lastActivatedTime.after(sunrise) ^ lastActivatedTime.after(sunset))) {
+ if (lastActivatedTime.isBefore(now) && (lastActivatedTime.isBefore(sunrise)
+ ^ lastActivatedTime.isBefore(sunset))) {
activate = mController.isActivated();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 0f580d818f91..4fafe34b3063 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -438,16 +438,7 @@ public class PackageDexOptimizer {
PackageDexUsage.DexUseInfo dexUseInfo = e.getValue();
pw.println(dex);
pw.increaseIndent();
- for (String isa : dexUseInfo.getLoaderIsas()) {
- String status = null;
- try {
- status = DexFile.getDexFileStatus(path, isa);
- } catch (IOException ioe) {
- status = "[Exception]: " + ioe.getMessage();
- }
- pw.println(isa + ": " + status);
- }
-
+ // TODO(calin): get the status of the oat file (needs installd call)
pw.println("class loader context: " + dexUseInfo.getClassLoaderContext());
if (dexUseInfo.isUsedByOtherApps()) {
pw.println("used be other apps: " + dexUseInfo.getLoadingPackages());
@@ -474,8 +465,9 @@ public class PackageDexOptimizer {
}
if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) {
- // If the dex files is used by other apps, we cannot use profile-guided compilation.
- return getNonProfileGuidedCompilerFilter(targetCompilerFilter);
+ // If the dex files is used by other apps, apply the shared filter.
+ return PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerService.REASON_SHARED);
}
return targetCompilerFilter;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ff52e0ebbbb9..8852a4db0cfe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -578,8 +578,9 @@ public class PackageManagerService extends IPackageManager.Stub
public static final int REASON_BACKGROUND_DEXOPT = 3;
public static final int REASON_AB_OTA = 4;
public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 5;
+ public static final int REASON_SHARED = 6;
- public static final int REASON_LAST = REASON_INACTIVE_PACKAGE_DOWNGRADE;
+ public static final int REASON_LAST = REASON_SHARED;
/** All dangerous permission names in the same order as the events in MetricsEvent */
private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
@@ -9819,19 +9820,6 @@ public class PackageManagerService extends IPackageManager.Stub
compilerFilter,
dexoptFlags));
- if (pkg.isSystemApp()) {
- // Only dexopt shared secondary dex files belonging to system apps to not slow down
- // too much boot after an OTA.
- int secondaryDexoptFlags = dexoptFlags |
- DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX |
- DexoptOptions.DEXOPT_ONLY_SHARED_DEX;
- mDexManager.dexoptSecondaryDex(new DexoptOptions(
- pkg.packageName,
- compilerFilter,
- secondaryDexoptFlags));
- }
-
- // TODO(shubhamajmera): Record secondary dexopt stats.
switch (primaryDexOptStaus) {
case PackageDexOptimizer.DEX_OPT_PERFORMED:
numberOfPackagesOptimized++;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 1a97a72cf2b3..19b0d9bc4b90 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -26,14 +26,19 @@ import dalvik.system.DexFile;
public class PackageManagerServiceCompilerMapping {
// Names for compilation reasons.
static final String REASON_STRINGS[] = {
- "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive"
+ "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared"
};
+ static final int REASON_SHARED_INDEX = 6;
+
// Static block to ensure the strings array is of the right length.
static {
if (PackageManagerService.REASON_LAST + 1 != REASON_STRINGS.length) {
throw new IllegalStateException("REASON_STRINGS not correct");
}
+ if (!"shared".equals(REASON_STRINGS[REASON_SHARED_INDEX])) {
+ throw new IllegalStateException("REASON_STRINGS not correct because of shared index");
+ }
}
private static String getSystemPropertyName(int reason) {
@@ -52,11 +57,18 @@ public class PackageManagerServiceCompilerMapping {
!DexFile.isValidCompilerFilter(sysPropValue)) {
throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
+ "(reason " + REASON_STRINGS[reason] + ")");
+ } else if (!isFilterAllowedForReason(reason, sysPropValue)) {
+ throw new IllegalStateException("Value \"" + sysPropValue +"\" not allowed "
+ + "(reason " + REASON_STRINGS[reason] + ")");
}
return sysPropValue;
}
+ private static boolean isFilterAllowedForReason(int reason, String filter) {
+ return reason != REASON_SHARED_INDEX || !DexFile.isProfileGuidedCompilerFilter(filter);
+ }
+
// Check that the properties are set and valid.
// Note: this is done in a separate method so this class can be statically initialized.
static void checkProperties() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1d7f66f54faf..d19bf445ef04 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -198,6 +198,7 @@ import android.util.EventLog;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.MutableBoolean;
+import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
@@ -296,13 +297,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
- static final int LONG_PRESS_BACK_NOTHING = 0;
- static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
-
static final int MULTI_PRESS_POWER_NOTHING = 0;
static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
+ static final int LONG_PRESS_BACK_NOTHING = 0;
+ static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
+
// Number of presses needed before we induce panic press behavior on the back button
static final int PANIC_PRESS_BACK_COUNT = 4;
static final int PANIC_PRESS_BACK_NOTHING = 0;
@@ -565,7 +566,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLongPressOnBackBehavior;
int mPanicPressOnBackBehavior;
int mShortPressOnSleepBehavior;
- int mShortPressWindowBehavior;
+ int mShortPressOnWindowBehavior;
volatile boolean mAwake;
boolean mScreenOnEarly;
boolean mScreenOnFully;
@@ -2180,9 +2181,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
}
- mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
+ mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
- mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
+ mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
}
mNavBarOpacityMode = res.getInteger(
@@ -6276,7 +6277,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
}
case KeyEvent.KEYCODE_WINDOW: {
- if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
+ if (mShortPressOnWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
if (mPictureInPictureVisible) {
// Consumes the key only if picture-in-picture is visible to show
// picture-in-picture control menu. This gives a chance to the foreground
@@ -8323,9 +8324,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
pw.print(" mSystemReady="); pw.print(mSystemReady);
pw.print(" mSystemBooted="); pw.println(mSystemBooted);
- pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
- pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
- pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
+ pw.print(prefix); pw.print("mLidState=");
+ pw.print(WindowManagerFuncs.lidStateToString(mLidState));
+ pw.print(" mLidOpenRotation=");
+ pw.println(Surface.rotationToString(mLidOpenRotation));
+ pw.print(prefix); pw.print("mCameraLensCoverState=");
+ pw.print(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
|| mForceClearedSystemUiFlags != 0) {
@@ -8343,16 +8347,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
pw.println(mWakeGestureEnabledSetting);
- pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
- pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
- pw.print(" mDockMode="); pw.print(mDockMode);
- pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
- pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
- pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
- pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
- pw.print(" mUserRotation="); pw.print(mUserRotation);
- pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
- pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
+ pw.print(prefix);
+ pw.print("mSupportAutoRotation="); pw.print(mSupportAutoRotation);
+ pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
+ pw.print(prefix); pw.print("mUiMode="); pw.print(Configuration.uiModeToString(mUiMode));
+ pw.print(" mDockMode="); pw.println(Intent.dockStateToString(mDockMode));
+ pw.print(prefix); pw.print("mEnableCarDockHomeCapture=");
+ pw.print(mEnableCarDockHomeCapture);
+ pw.print(" mCarDockRotation=");
+ pw.print(Surface.rotationToString(mCarDockRotation));
+ pw.print(" mDeskDockRotation=");
+ pw.println(Surface.rotationToString(mDeskDockRotation));
+ pw.print(prefix); pw.print("mUserRotationMode=");
+ pw.print(WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
+ pw.print(" mUserRotation="); pw.print(Surface.rotationToString(mUserRotation));
+ pw.print(" mAllowAllRotations=");
+ pw.println(allowAllRotationsToString(mAllowAllRotations));
+ pw.print(prefix); pw.print("mCurrentAppOrientation=");
+ pw.println(ActivityInfo.screenOrientationToString(mCurrentAppOrientation));
pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
pw.print(mCarDockEnablesAccelerometer);
pw.print(" mDeskDockEnablesAccelerometer=");
@@ -8361,23 +8373,54 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(mLidKeyboardAccessibility);
pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
- pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
+ pw.print(prefix); pw.print("mLidControlsSleep="); pw.println(mLidControlsSleep);
+ pw.print(prefix);
+ pw.print("mLongPressOnBackBehavior=");
+ pw.println(longPressOnBackBehaviorToString(mLongPressOnBackBehavior));
+ pw.print(prefix);
+ pw.print("mPanicPressOnBackBehavior=");
+ pw.println(panicPressOnBackBehaviorToString(mPanicPressOnBackBehavior));
+ pw.print(prefix);
+ pw.print("mLongPressOnHomeBehavior=");
+ pw.println(longPressOnHomeBehaviorToString(mLongPressOnHomeBehavior));
+ pw.print(prefix);
+ pw.print("mDoubleTapOnHomeBehavior=");
+ pw.println(doubleTapOnHomeBehaviorToString(mDoubleTapOnHomeBehavior));
+ pw.print(prefix);
+ pw.print("mShortPressOnPowerBehavior=");
+ pw.println(shortPressOnPowerBehaviorToString(mShortPressOnPowerBehavior));
pw.print(prefix);
- pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
+ pw.print("mLongPressOnPowerBehavior=");
+ pw.println(longPressOnPowerBehaviorToString(mLongPressOnPowerBehavior));
pw.print(prefix);
- pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
- pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+ pw.print("mDoublePressOnPowerBehavior=");
+ pw.println(multiPressOnPowerBehaviorToString(mDoublePressOnPowerBehavior));
pw.print(prefix);
- pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
- pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
- pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
- pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
- pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
+ pw.print("mTriplePressOnPowerBehavior=");
+ pw.println(multiPressOnPowerBehaviorToString(mTriplePressOnPowerBehavior));
+ pw.print(prefix);
+ pw.print("mShortPressOnSleepBehavior=");
+ pw.println(shortPressOnSleepBehaviorToString(mShortPressOnSleepBehavior));
+ pw.print(prefix);
+ pw.print("mShortPressOnWindowBehavior=");
+ pw.println(shortPressOnWindowBehaviorToString(mShortPressOnWindowBehavior));
+ pw.print(prefix);
+ pw.print("mHasSoftInput="); pw.print(mHasSoftInput);
+ pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed);
+ pw.print(prefix);
+ pw.print("mIncallPowerBehavior=");
+ pw.print(incallPowerBehaviorToString(mIncallPowerBehavior));
+ pw.print(" mIncallBackBehavior=");
+ pw.print(incallBackBehaviorToString(mIncallBackBehavior));
+ pw.print(" mEndcallBehavior=");
+ pw.println(endcallBehaviorToString(mEndcallBehavior));
+ pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
+ pw.print(prefix);
+ pw.print("mAwake="); pw.print(mAwake);
+ pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
- pw.print(prefix); pw.print("mOrientationSensorEnabled=");
- pw.println(mOrientationSensorEnabled);
pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
pw.print(","); pw.print(mOverscanScreenTop);
pw.print(") "); pw.print(mOverscanScreenWidth);
@@ -8443,8 +8486,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
pw.println(mLastInputMethodTargetWindow);
}
- pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
- pw.println(mDismissImeOnBackKeyPressed);
if (mStatusBar != null) {
pw.print(prefix); pw.print("mStatusBar=");
pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
@@ -8477,26 +8518,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
- pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
+ pw.print(prefix);
+ pw.print("mKeyguardOccludedChanged="); pw.print(mKeyguardOccludedChanged);
pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
pw.print(" mForceStatusBarFromKeyguard=");
pw.println(mForceStatusBarFromKeyguard);
- pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
- pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
- pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
- pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
- pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
- pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
- pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
- pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
- pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
- pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
+ pw.print(prefix); pw.print("mLandscapeRotation=");
+ pw.print(Surface.rotationToString(mLandscapeRotation));
+ pw.print(" mSeascapeRotation=");
+ pw.println(Surface.rotationToString(mSeascapeRotation));
+ pw.print(prefix); pw.print("mPortraitRotation=");
+ pw.print(Surface.rotationToString(mPortraitRotation));
+ pw.print(" mUpsideDownRotation=");
+ pw.println(Surface.rotationToString(mUpsideDownRotation));
+ pw.print(prefix); pw.print("mDemoHdmiRotation=");
+ pw.print(Surface.rotationToString(mDemoHdmiRotation));
pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
- pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
+ pw.print(prefix); pw.print("mUndockedHdmiRotation=");
+ pw.println(Surface.rotationToString(mUndockedHdmiRotation));
if (mHasFeatureLeanback) {
pw.print(prefix);
pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
@@ -8523,5 +8566,169 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mKeyguardDelegate != null) {
mKeyguardDelegate.dump(prefix, pw);
}
+
+ pw.print(prefix); pw.println("Looper state:");
+ mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
+ }
+
+ private static String allowAllRotationsToString(int allowAll) {
+ switch (allowAll) {
+ case -1:
+ return "unknown";
+ case 0:
+ return "false";
+ case 1:
+ return "true";
+ default:
+ return Integer.toString(allowAll);
+ }
+ }
+
+ private static String endcallBehaviorToString(int behavior) {
+ StringBuilder sb = new StringBuilder();
+ if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) {
+ sb.append("home|");
+ }
+ if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
+ sb.append("sleep|");
+ }
+
+ final int N = sb.length();
+ if (N == 0) {
+ return "<nothing>";
+ } else {
+ // Chop off the trailing '|'
+ return sb.substring(0, N - 1);
+ }
+ }
+
+ private static String incallPowerBehaviorToString(int behavior) {
+ if ((behavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0) {
+ return "hangup";
+ } else {
+ return "sleep";
+ }
+ }
+
+ private static String incallBackBehaviorToString(int behavior) {
+ if ((behavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0) {
+ return "hangup";
+ } else {
+ return "<nothing>";
+ }
+ }
+
+ private static String longPressOnBackBehaviorToString(int behavior) {
+ switch (behavior) {
+ case LONG_PRESS_BACK_NOTHING:
+ return "LONG_PRESS_BACK_NOTHING";
+ case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
+ return "LONG_PRESS_BACK_GO_TO_VOICE_ASSIST";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String panicPressOnBackBehaviorToString(int behavior) {
+ switch (behavior) {
+ case PANIC_PRESS_BACK_NOTHING:
+ return "PANIC_PRESS_BACK_NOTHING";
+ case PANIC_PRESS_BACK_HOME:
+ return "PANIC_PRESS_BACK_HOME";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String longPressOnHomeBehaviorToString(int behavior) {
+ switch (behavior) {
+ case LONG_PRESS_HOME_NOTHING:
+ return "LONG_PRESS_HOME_NOTHING";
+ case LONG_PRESS_HOME_ALL_APPS:
+ return "LONG_PRESS_HOME_ALL_APPS";
+ case LONG_PRESS_HOME_ASSIST:
+ return "LONG_PRESS_HOME_ASSIST";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String doubleTapOnHomeBehaviorToString(int behavior) {
+ switch (behavior) {
+ case DOUBLE_TAP_HOME_NOTHING:
+ return "DOUBLE_TAP_HOME_NOTHING";
+ case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
+ return "DOUBLE_TAP_HOME_RECENT_SYSTEM_UI";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String shortPressOnPowerBehaviorToString(int behavior) {
+ switch (behavior) {
+ case SHORT_PRESS_POWER_NOTHING:
+ return "SHORT_PRESS_POWER_NOTHING";
+ case SHORT_PRESS_POWER_GO_TO_SLEEP:
+ return "SHORT_PRESS_POWER_GO_TO_SLEEP";
+ case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
+ return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP";
+ case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
+ return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME";
+ case SHORT_PRESS_POWER_GO_HOME:
+ return "SHORT_PRESS_POWER_GO_HOME";
+ case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME:
+ return "SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String longPressOnPowerBehaviorToString(int behavior) {
+ switch (behavior) {
+ case LONG_PRESS_POWER_NOTHING:
+ return "LONG_PRESS_POWER_NOTHING";
+ case LONG_PRESS_POWER_GLOBAL_ACTIONS:
+ return "LONG_PRESS_POWER_GLOBAL_ACTIONS";
+ case LONG_PRESS_POWER_SHUT_OFF:
+ return "LONG_PRESS_POWER_SHUT_OFF";
+ case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
+ return "LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+ private static String multiPressOnPowerBehaviorToString(int behavior) {
+ switch (behavior) {
+ case MULTI_PRESS_POWER_NOTHING:
+ return "MULTI_PRESS_POWER_NOTHING";
+ case MULTI_PRESS_POWER_THEATER_MODE:
+ return "MULTI_PRESS_POWER_THEATER_MODE";
+ case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
+ return "MULTI_PRESS_POWER_BRIGHTNESS_BOOST";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String shortPressOnSleepBehaviorToString(int behavior) {
+ switch (behavior) {
+ case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
+ return "SHORT_PRESS_SLEEP_GO_TO_SLEEP";
+ case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
+ return "SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
+ private static String shortPressOnWindowBehaviorToString(int behavior) {
+ switch (behavior) {
+ case SHORT_PRESS_WINDOW_NOTHING:
+ return "SHORT_PRESS_WINDOW_NOTHING";
+ case SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE:
+ return "SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE";
+ default:
+ return Integer.toString(behavior);
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 64f64c0d45d6..169fd278f665 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -26,6 +26,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Slog;
+import android.view.Surface;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -236,7 +237,7 @@ public abstract class WindowOrientationListener {
pw.println(prefix + TAG);
prefix += " ";
pw.println(prefix + "mEnabled=" + mEnabled);
- pw.println(prefix + "mCurrentRotation=" + mCurrentRotation);
+ pw.println(prefix + "mCurrentRotation=" + Surface.rotationToString(mCurrentRotation));
pw.println(prefix + "mSensorType=" + mSensorType);
pw.println(prefix + "mSensor=" + mSensor);
pw.println(prefix + "mRate=" + mRate);
@@ -1026,8 +1027,9 @@ public abstract class WindowOrientationListener {
public void dumpLocked(PrintWriter pw, String prefix) {
pw.println(prefix + "OrientationSensorJudge");
prefix += " ";
- pw.println(prefix + "mDesiredRotation=" + mDesiredRotation);
- pw.println(prefix + "mProposedRotation=" + mProposedRotation);
+ pw.println(prefix + "mDesiredRotation=" + Surface.rotationToString(mDesiredRotation));
+ pw.println(prefix + "mProposedRotation="
+ + Surface.rotationToString(mProposedRotation));
pw.println(prefix + "mTouching=" + mTouching);
pw.println(prefix + "mTouchEndedTimestampNanos=" + mTouchEndedTimestampNanos);
}
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 50e5e7bd2312..70cd54ffd09d 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,5 +1,7 @@
package com.android.server.policy.keyguard;
+import static android.view.Display.INVALID_DISPLAY;
+
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -13,6 +15,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
+import android.view.WindowManagerPolicy;
import android.view.WindowManagerPolicy.OnKeyguardExitResult;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -201,7 +204,10 @@ public class KeyguardServiceDelegate {
mKeyguardState.reset();
mHandler.post(() -> {
try {
- ActivityManager.getService().setLockScreenShown(true);
+ // There are no longer any keyguard windows on secondary displays, so pass
+ // INVALID_DISPLAY. All that means is that showWhenLocked activities on
+ // secondary displays now get to show.
+ ActivityManager.getService().setLockScreenShown(true, INVALID_DISPLAY);
} catch (RemoteException e) {
// Local call.
}
@@ -412,13 +418,45 @@ public class KeyguardServiceDelegate {
pw.println(prefix + "systemIsReady=" + mKeyguardState.systemIsReady);
pw.println(prefix + "deviceHasKeyguard=" + mKeyguardState.deviceHasKeyguard);
pw.println(prefix + "enabled=" + mKeyguardState.enabled);
- pw.println(prefix + "offReason=" + mKeyguardState.offReason);
+ pw.println(prefix + "offReason=" +
+ WindowManagerPolicy.offReasonToString(mKeyguardState.offReason));
pw.println(prefix + "currentUser=" + mKeyguardState.currentUser);
pw.println(prefix + "bootCompleted=" + mKeyguardState.bootCompleted);
- pw.println(prefix + "screenState=" + mKeyguardState.screenState);
- pw.println(prefix + "interactiveState=" + mKeyguardState.interactiveState);
+ pw.println(prefix + "screenState=" + screenStateToString(mKeyguardState.screenState));
+ pw.println(prefix + "interactiveState=" +
+ interactiveStateToString(mKeyguardState.interactiveState));
if (mKeyguardService != null) {
mKeyguardService.dump(prefix, pw);
}
}
+
+ private static String screenStateToString(int screen) {
+ switch (screen) {
+ case SCREEN_STATE_OFF:
+ return "SCREEN_STATE_OFF";
+ case SCREEN_STATE_TURNING_ON:
+ return "SCREEN_STATE_TURNING_ON";
+ case SCREEN_STATE_ON:
+ return "SCREEN_STATE_ON";
+ case SCREEN_STATE_TURNING_OFF:
+ return "SCREEN_STATE_TURNING_OFF";
+ default:
+ return Integer.toString(screen);
+ }
+ }
+
+ private static String interactiveStateToString(int interactive) {
+ switch (interactive) {
+ case INTERACTIVE_STATE_SLEEP:
+ return "INTERACTIVE_STATE_SLEEP";
+ case INTERACTIVE_STATE_WAKING:
+ return "INTERACTIVE_STATE_WAKING";
+ case INTERACTIVE_STATE_AWAKE:
+ return "INTERACTIVE_STATE_AWAKE";
+ case INTERACTIVE_STATE_GOING_TO_SLEEP:
+ return "INTERACTIVE_STATE_GOING_TO_SLEEP";
+ default:
+ return Integer.toString(interactive);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 3b701302aae1..12ca89a93d02 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -120,7 +120,7 @@ public final class PowerManagerService extends SystemService
implements Watchdog.Monitor {
private static final String TAG = "PowerManagerService";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
private static final boolean DEBUG_SPEW = DEBUG && true;
// Message: Sent when a user activity timeout occurs to update the power state.
@@ -1569,12 +1569,15 @@ public final class PowerManagerService extends SystemService
return true;
}
- private void setWakefulnessLocked(int wakefulness, int reason) {
+ @VisibleForTesting
+ void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
- mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
+ if (mNotifier != null) {
+ mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
+ }
}
}
@@ -2432,11 +2435,8 @@ public final class PowerManagerService extends SystemService
return value >= -1.0f && value <= 1.0f;
}
- private int getDesiredScreenPolicyLocked() {
- if (mIsVrModeEnabled) {
- return DisplayPowerRequest.POLICY_VR;
- }
-
+ @VisibleForTesting
+ int getDesiredScreenPolicyLocked() {
if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
return DisplayPowerRequest.POLICY_OFF;
}
@@ -2452,6 +2452,13 @@ public final class PowerManagerService extends SystemService
// doze after screen off. This causes the screen off transition to be skipped.
}
+ // It is important that POLICY_VR check happens after the wakefulness checks above so
+ // that VR-mode does not prevent displays from transitioning to the correct state when
+ // dozing or sleeping.
+ if (mIsVrModeEnabled) {
+ return DisplayPowerRequest.POLICY_VR;
+ }
+
if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|| (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
|| !mBootCompleted
@@ -3113,6 +3120,11 @@ public final class PowerManagerService extends SystemService
}
}
+ @VisibleForTesting
+ void setVrModeEnabled(boolean enabled) {
+ mIsVrModeEnabled = enabled;
+ }
+
private void powerHintInternal(int hintId, int data) {
nativeSendPowerHint(hintId, data);
}
@@ -3810,7 +3822,7 @@ public final class PowerManagerService extends SystemService
synchronized (mLock) {
if (mIsVrModeEnabled != enabled) {
- mIsVrModeEnabled = enabled;
+ setVrModeEnabled(enabled);
mDirty |= DIRTY_VR_MODE_CHANGED;
updatePowerStateLocked();
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
new file mode 100644
index 000000000000..5b77b1ed5269
--- /dev/null
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.stats;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IStatsCompanionService;
+import android.os.IStatsManager;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+
+/**
+ * Helper service for statsd (the native stats management service in cmds/statsd/).
+ * Used for registering and receiving alarms on behalf of statsd.
+ */
+public class StatsCompanionService extends IStatsCompanionService.Stub {
+ static final String TAG = "StatsCompanionService";
+ static final boolean DEBUG = true;
+
+ private final Context mContext;
+ private final AlarmManager mAlarmManager;
+ private final IStatsManager mStatsd;
+
+ private final PendingIntent mAnomalyAlarmIntent;
+ private final PendingIntent mPollingAlarmIntent;
+
+ public final static class AnomalyAlarmReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred.");
+ // TODO: mStatsd.informAlarm(); // should be twoway so device won't sleep before acting?
+ // AlarmManager releases its own wakelock here.
+ }
+ };
+
+ public final static class PollingAlarmReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Slog.d(TAG, "Time to poll something.");
+ // TODO: mStatsd.poll(); // should be twoway so device won't sleep before acting?
+ // AlarmManager releases its own wakelock here.
+ }
+ };
+
+ public StatsCompanionService(Context context) {
+ super();
+ mContext = context;
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+
+ mAnomalyAlarmIntent = PendingIntent.getBroadcast(mContext, 0,
+ new Intent(mContext, AnomalyAlarmReceiver.class), 0);
+ mPollingAlarmIntent = PendingIntent.getBroadcast(mContext, 0,
+ new Intent(mContext, PollingAlarmReceiver.class), 0);
+
+ mStatsd = getStatsdService();
+ }
+
+ /** Returns the statsd IBinder service */
+ public static IStatsManager getStatsdService() {
+ return IStatsManager.Stub.asInterface(ServiceManager.getService("statsd"));
+ }
+
+ public static final class Lifecycle extends SystemService {
+ private StatsCompanionService mStatsCompanionService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mStatsCompanionService = new StatsCompanionService(getContext());
+ try {
+ publishBinderService(Context.STATS_COMPANION_SERVICE, mStatsCompanionService);
+ if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to publishBinderService", e);
+ }
+ }
+ }
+
+ @Override // Binder call
+ public void setAnomalyAlarm(long timestampMs) {
+ enforceCallingPermission();
+ if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs);
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens.
+ // This alarm is inexact, leaving its exactness completely up to the OS optimizations.
+ // AlarmManager will automatically cancel any previous mAnomalyAlarmIntent alarm.
+ mAlarmManager.set(AlarmManager.RTC, timestampMs, mAnomalyAlarmIntent);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ }
+
+ @Override // Binder call
+ public void cancelAnomalyAlarm() {
+ enforceCallingPermission();
+ if (DEBUG) Slog.d(TAG, "Cancelling anomaly alarm");
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ mAlarmManager.cancel(mAnomalyAlarmIntent);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ }
+
+ @Override // Binder call
+ public void setPollingAlarms(long timestampMs, long intervalMs) {
+ enforceCallingPermission();
+ if (DEBUG) Slog.d(TAG, "Setting polling alarm for " + timestampMs
+ + " every " + intervalMs + "ms");
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens.
+ // This alarm is inexact, leaving its exactness completely up to the OS optimizations.
+ // TODO: totally inexact means that stats per bucket could be quite off. Is this okay?
+ mAlarmManager.setRepeating(AlarmManager.RTC, timestampMs, intervalMs,
+ mPollingAlarmIntent);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ }
+
+ @Override // Binder call
+ public void cancelPollingAlarms() {
+ enforceCallingPermission();
+ if (DEBUG) Slog.d(TAG, "Cancelling polling alarm");
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ mAlarmManager.cancel(mPollingAlarmIntent);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ }
+
+ private void enforceCallingPermission() {
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return;
+ }
+ mContext.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null);
+ }
+
+}
diff --git a/services/core/java/com/android/server/timezone/IntentHelper.java b/services/core/java/com/android/server/timezone/IntentHelper.java
index 0cb90657480e..5de543213009 100644
--- a/services/core/java/com/android/server/timezone/IntentHelper.java
+++ b/services/core/java/com/android/server/timezone/IntentHelper.java
@@ -23,15 +23,22 @@ package com.android.server.timezone;
*/
interface IntentHelper {
- void initialize(String updateAppPackageName, String dataAppPackageName, Listener listener);
+ void initialize(String updateAppPackageName, String dataAppPackageName,
+ PackageTracker packageTracker);
void sendTriggerUpdateCheck(CheckToken checkToken);
- void enableReliabilityTriggering();
+ /**
+ * Schedule a "reliability trigger" after at least minimumDelayMillis, replacing any existing
+ * scheduled one. A reliability trigger ensures that the {@link PackageTracker} can pick up
+ * reliably if a previous update check did not complete for some reason. It can happen when
+ * the device is idle. The trigger is expected to call
+ * {@link PackageTracker#triggerUpdateIfNeeded(boolean)} with a {@code false} value.
+ */
+ void scheduleReliabilityTrigger(long minimumDelayMillis);
- void disableReliabilityTriggering();
-
- interface Listener {
- void triggerUpdateIfNeeded(boolean packageUpdated);
- }
+ /**
+ * Make sure there is no reliability trigger scheduled. No-op if there wasn't one.
+ */
+ void unscheduleReliabilityTrigger();
}
diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
index 6db70cd870db..bc0f6e4b283b 100644
--- a/services/core/java/com/android/server/timezone/IntentHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
@@ -36,16 +36,13 @@ final class IntentHelperImpl implements IntentHelper {
private final Context mContext;
private String mUpdaterAppPackageName;
- private boolean mReliabilityReceiverEnabled;
- private Receiver mReliabilityReceiver;
-
IntentHelperImpl(Context context) {
mContext = context;
}
@Override
- public void initialize(
- String updaterAppPackageName, String dataAppPackageName, Listener listener) {
+ public void initialize(String updaterAppPackageName, String dataAppPackageName,
+ PackageTracker packageTracker) {
mUpdaterAppPackageName = updaterAppPackageName;
// Register for events of interest.
@@ -78,10 +75,8 @@ final class IntentHelperImpl implements IntentHelper {
// We do not register for ACTION_PACKAGE_DATA_CLEARED because the updater / data apps are
// not expected to need local data.
- Receiver packageUpdateReceiver = new Receiver(listener, true /* packageUpdated */);
+ Receiver packageUpdateReceiver = new Receiver(packageTracker);
mContext.registerReceiver(packageUpdateReceiver, packageIntentFilter);
-
- mReliabilityReceiver = new Receiver(listener, false /* packageUpdated */);
}
/** Sends an intent to trigger an update check. */
@@ -93,39 +88,26 @@ final class IntentHelperImpl implements IntentHelper {
}
@Override
- public synchronized void enableReliabilityTriggering() {
- if (!mReliabilityReceiverEnabled) {
- // The intent filter that exists to make updates reliable in the event of failures /
- // reboots.
- IntentFilter reliabilityIntentFilter = new IntentFilter();
- reliabilityIntentFilter.addAction(Intent.ACTION_IDLE_MAINTENANCE_START);
- mContext.registerReceiver(mReliabilityReceiver, reliabilityIntentFilter);
- mReliabilityReceiverEnabled = true;
- }
+ public synchronized void scheduleReliabilityTrigger(long minimumDelayMillis) {
+ TimeZoneUpdateIdler.schedule(mContext, minimumDelayMillis);
}
@Override
- public synchronized void disableReliabilityTriggering() {
- if (mReliabilityReceiverEnabled) {
- mContext.unregisterReceiver(mReliabilityReceiver);
- mReliabilityReceiverEnabled = false;
- }
+ public synchronized void unscheduleReliabilityTrigger() {
+ TimeZoneUpdateIdler.unschedule(mContext);
}
private static class Receiver extends BroadcastReceiver {
- private final Listener mListener;
- private final boolean mPackageUpdated;
+ private final PackageTracker mPackageTracker;
- private Receiver(Listener listener, boolean packageUpdated) {
- mListener = listener;
- mPackageUpdated = packageUpdated;
+ private Receiver(PackageTracker packageTracker) {
+ mPackageTracker = packageTracker;
}
@Override
public void onReceive(Context context, Intent intent) {
Slog.d(TAG, "Received intent: " + intent.toString());
- mListener.triggerUpdateIfNeeded(mPackageUpdated);
+ mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */);
}
}
-
}
diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java
index 24e0fe4841bc..f0306b9b0c38 100644
--- a/services/core/java/com/android/server/timezone/PackageTracker.java
+++ b/services/core/java/com/android/server/timezone/PackageTracker.java
@@ -51,7 +51,7 @@ import java.io.PrintWriter;
*/
// Also made non-final so it can be mocked.
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class PackageTracker implements IntentHelper.Listener {
+public class PackageTracker {
private static final String TAG = "timezone.PackageTracker";
private final PackageManagerHelper mPackageManagerHelper;
@@ -72,6 +72,13 @@ public class PackageTracker implements IntentHelper.Listener {
// The number of failed checks in a row before reliability checks should stop happening.
private long mFailedCheckRetryCount;
+ /*
+ * The minimum delay between a successive reliability triggers / other operations. Should to be
+ * larger than mCheckTimeAllowedMillis to avoid reliability triggers happening during package
+ * update checks.
+ */
+ private int mDelayBeforeReliabilityCheckMillis;
+
// Reliability check state: If a check was triggered but not acknowledged within
// mCheckTimeAllowedMillis then another one can be triggered.
private Long mLastTriggerTimestamp = null;
@@ -122,6 +129,7 @@ public class PackageTracker implements IntentHelper.Listener {
mDataAppPackageName = mConfigHelper.getDataAppPackageName();
mCheckTimeAllowedMillis = mConfigHelper.getCheckTimeAllowedMillis();
mFailedCheckRetryCount = mConfigHelper.getFailedCheckRetryCount();
+ mDelayBeforeReliabilityCheckMillis = mCheckTimeAllowedMillis + (60 * 1000);
// Validate the device configuration including the application packages.
// The manifest entries in the apps themselves are not validated until use as they can
@@ -135,9 +143,10 @@ public class PackageTracker implements IntentHelper.Listener {
// Initialize the intent helper.
mIntentHelper.initialize(mUpdateAppPackageName, mDataAppPackageName, this);
- // Enable the reliability triggering so we will have at least one reliability trigger if
- // a package isn't updated.
- mIntentHelper.enableReliabilityTriggering();
+ // Schedule a reliability trigger so we will have at least one after boot. This will allow
+ // us to catch if a package updated wasn't handled to completion. There's no hurry: it's ok
+ // to delay for a while before doing this even if idle.
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
Slog.i(TAG, "Time zone updater / data package tracking enabled");
}
@@ -195,7 +204,6 @@ public class PackageTracker implements IntentHelper.Listener {
* @param packageChanged true if this method was called because a known packaged definitely
* changed, false if the cause is a reliability trigger
*/
- @Override
public synchronized void triggerUpdateIfNeeded(boolean packageChanged) {
if (!mTrackingEnabled) {
throw new IllegalStateException("Unexpected call. Tracking is disabled.");
@@ -212,8 +220,8 @@ public class PackageTracker implements IntentHelper.Listener {
+ " updaterApp=" + updaterAppManifestValid
+ ", dataApp=" + dataAppManifestValid);
- // There's no point in doing reliability checks if the current packages are bad.
- mIntentHelper.disableReliabilityTriggering();
+ // There's no point in doing any reliability triggers if the current packages are bad.
+ mIntentHelper.unscheduleReliabilityTrigger();
return;
}
@@ -238,7 +246,8 @@ public class PackageTracker implements IntentHelper.Listener {
Slog.d(TAG,
"triggerUpdateIfNeeded: checkComplete call is not yet overdue."
+ " Not triggering.");
- // Not doing any work, but also not disabling future reliability triggers.
+ // Don't do any work now but we do schedule a future reliability trigger.
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
return;
}
} else if (mCheckFailureCount > mFailedCheckRetryCount) {
@@ -247,13 +256,13 @@ public class PackageTracker implements IntentHelper.Listener {
Slog.i(TAG, "triggerUpdateIfNeeded: number of allowed consecutive check failures"
+ " exceeded. Stopping reliability triggers until next reboot or package"
+ " update.");
- mIntentHelper.disableReliabilityTriggering();
+ mIntentHelper.unscheduleReliabilityTrigger();
return;
} else if (mCheckFailureCount == 0) {
// Case 4.
Slog.i(TAG, "triggerUpdateIfNeeded: No reliability check required. Last check was"
+ " successful.");
- mIntentHelper.disableReliabilityTriggering();
+ mIntentHelper.unscheduleReliabilityTrigger();
return;
}
}
@@ -263,7 +272,7 @@ public class PackageTracker implements IntentHelper.Listener {
if (currentInstalledVersions == null) {
// This should not happen if the device is configured in a valid way.
Slog.e(TAG, "triggerUpdateIfNeeded: currentInstalledVersions was null");
- mIntentHelper.disableReliabilityTriggering();
+ mIntentHelper.unscheduleReliabilityTrigger();
return;
}
@@ -288,7 +297,7 @@ public class PackageTracker implements IntentHelper.Listener {
// The last check succeeded and nothing has changed. Do nothing and disable
// reliability checks.
Slog.i(TAG, "triggerUpdateIfNeeded: Prior check succeeded. No need to trigger.");
- mIntentHelper.disableReliabilityTriggering();
+ mIntentHelper.unscheduleReliabilityTrigger();
return;
}
}
@@ -299,6 +308,8 @@ public class PackageTracker implements IntentHelper.Listener {
if (checkToken == null) {
Slog.w(TAG, "triggerUpdateIfNeeded: Unable to generate check token."
+ " Not sending check request.");
+ // Trigger again later: perhaps we'll have better luck.
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
return;
}
@@ -309,9 +320,9 @@ public class PackageTracker implements IntentHelper.Listener {
// Update the reliability check state in case the update fails.
setCheckInProgress();
- // Enable reliability triggering in case the check doesn't succeed and there is no
- // response at all. Enabling reliability triggering is idempotent.
- mIntentHelper.enableReliabilityTriggering();
+ // Schedule a reliability trigger in case the update check doesn't succeed and there is no
+ // response at all. It will be cancelled if the check is successful in recordCheckResult.
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
}
/**
@@ -370,9 +381,9 @@ public class PackageTracker implements IntentHelper.Listener {
+ " storage state.");
mPackageStatusStorage.resetCheckState();
- // Enable reliability triggering and reset the failure count so we know that the
+ // Schedule a reliability trigger and reset the failure count so we know that the
// next reliability trigger will do something.
- mIntentHelper.enableReliabilityTriggering();
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
mCheckFailureCount = 0;
} else {
// This is the expected case when tracking is enabled: a check was triggered and it has
@@ -385,13 +396,13 @@ public class PackageTracker implements IntentHelper.Listener {
setCheckComplete();
if (success) {
- // Since the check was successful, no more reliability checks are required until
+ // Since the check was successful, no reliability trigger is required until
// there is a package change.
- mIntentHelper.disableReliabilityTriggering();
+ mIntentHelper.unscheduleReliabilityTrigger();
mCheckFailureCount = 0;
} else {
- // Enable reliability triggering to potentially check again in future.
- mIntentHelper.enableReliabilityTriggering();
+ // Enable schedule a reliability trigger to check again in future.
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
mCheckFailureCount++;
}
} else {
@@ -400,8 +411,8 @@ public class PackageTracker implements IntentHelper.Listener {
Slog.i(TAG, "recordCheckResult: could not update token=" + checkToken
+ " with success=" + success + ". Optimistic lock failure");
- // Enable reliability triggering to potentially try again in future.
- mIntentHelper.enableReliabilityTriggering();
+ // Schedule a reliability trigger to potentially try again in future.
+ mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
mCheckFailureCount++;
}
}
@@ -515,6 +526,7 @@ public class PackageTracker implements IntentHelper.Listener {
", mUpdateAppPackageName='" + mUpdateAppPackageName + '\'' +
", mDataAppPackageName='" + mDataAppPackageName + '\'' +
", mCheckTimeAllowedMillis=" + mCheckTimeAllowedMillis +
+ ", mDelayBeforeReliabilityCheckMillis=" + mDelayBeforeReliabilityCheckMillis +
", mFailedCheckRetryCount=" + mFailedCheckRetryCount +
", mLastTriggerTimestamp=" + mLastTriggerTimestamp +
", mCheckTriggered=" + mCheckTriggered +
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index 3ad4419c7273..6824a597a5f8 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -69,18 +69,22 @@ public final class RulesManagerService extends IRulesManager.Stub {
DistroVersion.CURRENT_FORMAT_MINOR_VERSION);
public static class Lifecycle extends SystemService {
- private RulesManagerService mService;
-
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
- mService = RulesManagerService.create(getContext());
- mService.start();
+ RulesManagerService service = RulesManagerService.create(getContext());
+ service.start();
+
+ // Publish the binder service so it can be accessed from other (appropriately
+ // permissioned) processes.
+ publishBinderService(Context.TIME_ZONE_RULES_MANAGER_SERVICE, service);
- publishBinderService(Context.TIME_ZONE_RULES_MANAGER_SERVICE, mService);
+ // Publish the service instance locally so we can use it directly from within the system
+ // server from TimeZoneUpdateIdler.
+ publishLocalService(RulesManagerService.class, service);
}
}
@@ -496,6 +500,16 @@ public final class RulesManagerService extends IRulesManager.Stub {
mPackageTracker.dump(pw);
}
+ /**
+ * Called when the device is considered idle.
+ */
+ void notifyIdle() {
+ // No package has changed: we are just triggering because the device is idle and there
+ // *might* be work to do.
+ final boolean packageChanged = false;
+ mPackageTracker.triggerUpdateIfNeeded(packageChanged);
+ }
+
@Override
public String toString() {
return "RulesManagerService{" +
diff --git a/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java b/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java
new file mode 100644
index 000000000000..a7767a4fbd66
--- /dev/null
+++ b/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezone;
+
+import com.android.server.LocalServices;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.Slog;
+
+/**
+ * A JobService used to trigger time zone rules update work when a device falls idle.
+ */
+public final class TimeZoneUpdateIdler extends JobService {
+
+ private static final String TAG = "timezone.TimeZoneUpdateIdler";
+
+ /** The static job ID used to handle on-idle work. */
+ // Must be unique within UID (system service)
+ private static final int TIME_ZONE_UPDATE_IDLE_JOB_ID = 27042305;
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ RulesManagerService rulesManagerService =
+ LocalServices.getService(RulesManagerService.class);
+
+ Slog.d(TAG, "onStartJob() called");
+
+ // Note: notifyIdle() explicitly handles canceling / re-scheduling so no need to reschedule
+ // here.
+ rulesManagerService.notifyIdle();
+
+ // Everything is handled synchronously. We are done.
+ return false;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ // Reschedule if stopped unless it was cancelled due to unschedule().
+ boolean reschedule = params.getStopReason() != JobParameters.REASON_CANCELED;
+ Slog.d(TAG, "onStopJob() called: Reschedule=" + reschedule);
+ return reschedule;
+ }
+
+ /**
+ * Schedules the TimeZoneUpdateIdler job service to run once.
+ *
+ * @param context Context to use to get a job scheduler.
+ */
+ public static void schedule(Context context, long minimumDelayMillis) {
+ // Request that the JobScheduler tell us when the device falls idle.
+ JobScheduler jobScheduler =
+ (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+
+ // The TimeZoneUpdateIdler will send an intent that will trigger the Receiver.
+ ComponentName idlerJobServiceName =
+ new ComponentName(context, TimeZoneUpdateIdler.class);
+
+ // We require the device is idle, but also that it is charging to be as non-invasive as
+ // we can.
+ JobInfo.Builder jobInfoBuilder =
+ new JobInfo.Builder(TIME_ZONE_UPDATE_IDLE_JOB_ID, idlerJobServiceName)
+ .setRequiresDeviceIdle(true)
+ .setRequiresCharging(true)
+ .setMinimumLatency(minimumDelayMillis);
+
+ Slog.d(TAG, "schedule() called: minimumDelayMillis=" + minimumDelayMillis);
+ jobScheduler.schedule(jobInfoBuilder.build());
+ }
+
+ /**
+ * Unschedules the TimeZoneUpdateIdler job service.
+ *
+ * @param context Context to use to get a job scheduler.
+ */
+ public static void unschedule(Context context) {
+ JobScheduler jobScheduler =
+ (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+ Slog.d(TAG, "unschedule() called");
+ jobScheduler.cancel(TIME_ZONE_UPDATE_IDLE_JOB_ID);
+ }
+}
diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java
index 30a8cccb6ad5..71304a7a4701 100644
--- a/services/core/java/com/android/server/twilight/TwilightState.java
+++ b/services/core/java/com/android/server/twilight/TwilightState.java
@@ -18,7 +18,10 @@ package com.android.server.twilight;
import android.text.format.DateFormat;
-import java.util.Calendar;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.TimeZone;
/**
* The twilight state, consisting of the sunrise and sunset times (in millis) for the current
@@ -45,12 +48,11 @@ public final class TwilightState {
}
/**
- * Returns a new {@link Calendar} instance initialized to {@link #sunriseTimeMillis()}.
+ * Returns a new {@link LocalDateTime} instance initialized to {@link #sunriseTimeMillis()}.
*/
- public Calendar sunrise() {
- final Calendar sunrise = Calendar.getInstance();
- sunrise.setTimeInMillis(mSunriseTimeMillis);
- return sunrise;
+ public LocalDateTime sunrise() {
+ final ZoneId zoneId = TimeZone.getDefault().toZoneId();
+ return LocalDateTime.ofInstant(Instant.ofEpochMilli(mSunriseTimeMillis), zoneId);
}
/**
@@ -62,12 +64,11 @@ public final class TwilightState {
}
/**
- * Returns a new {@link Calendar} instance initialized to {@link #sunsetTimeMillis()}.
+ * Returns a new {@link LocalDateTime} instance initialized to {@link #sunsetTimeMillis()}.
*/
- public Calendar sunset() {
- final Calendar sunset = Calendar.getInstance();
- sunset.setTimeInMillis(mSunsetTimeMillis);
- return sunset;
+ public LocalDateTime sunset() {
+ final ZoneId zoneId = TimeZone.getDefault().toZoneId();
+ return LocalDateTime.ofInstant(Instant.ofEpochMilli(mSunsetTimeMillis), zoneId);
}
/**
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index bf769ed46bc1..1e334b83d8b0 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -304,6 +304,6 @@ public class SystemImpl implements SystemInterface {
// flags declaring we want extra info from the package manager for webview providers
private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
- | PackageManager.MATCH_ANY_USER;
+ | PackageManager.GET_SIGNATURES | PackageManager.GET_SHARED_LIBRARY_FILES
+ | PackageManager.MATCH_DEBUG_TRIAGED_MISSING | PackageManager.MATCH_ANY_USER;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 817a01c5c8d7..98a1bd359b55 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1722,21 +1722,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
out.set(mContentRect);
}
- TaskStack addStackToDisplay(int stackId, boolean onTop) {
+ TaskStack addStackToDisplay(int stackId, boolean onTop, StackWindowController controller) {
if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
+ mDisplayId);
TaskStack stack = getStackById(stackId);
if (stack != null) {
- // It's already attached to the display...clear mDeferRemoval and move stack to
- // appropriate z-order on display as needed.
+ // It's already attached to the display...clear mDeferRemoval, set controller, and move
+ // stack to appropriate z-order on display as needed.
stack.mDeferRemoval = false;
+ stack.setController(controller);
// We're not moving the display to front when we're adding stacks, only when
// requested to change the position of stack explicitly.
mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
false /* includingParents */);
} else {
- stack = new TaskStack(mService, stackId);
+ stack = new TaskStack(mService, stackId, controller);
mTaskStackContainers.addStackToDisplay(stack, onTop);
}
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index a50ed71afdb1..c0a4cb72a348 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -18,8 +18,6 @@ package com.android.server.wm;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import android.app.ActivityManager.StackId;
-import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
@@ -76,8 +74,7 @@ public class StackWindowController
+ " to unknown displayId=" + displayId);
}
- final TaskStack stack = dc.addStackToDisplay(stackId, onTop);
- stack.setController(this);
+ dc.addStackToDisplay(stackId, onTop, this);
getRawBounds(outBounds);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 463240228fb6..751769a63d62 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -297,7 +297,7 @@ class TaskSnapshotController {
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
topChild.getConfiguration().orientation, mainWindow.mStableInsets,
- false /* reduced */, 1.0f /* scale */);
+ ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */);
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 126d820e69b6..7cb90de49b1a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -149,9 +149,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
Rect mPreAnimationBounds = new Rect();
- TaskStack(WindowManagerService service, int stackId) {
+ TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
mService = service;
mStackId = stackId;
+ setController(controller);
mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_minimize_thickness);
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 57271fa10950..948c028d46ca 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -103,6 +103,7 @@ import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.soundtrigger.SoundTriggerService;
+import com.android.server.stats.StatsCompanionService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
import com.android.server.telecom.TelecomLoaderService;
@@ -1146,20 +1147,6 @@ public final class SystemServer {
traceEnd();
}
- /*
- * StorageManagerService has a few dependencies: Notification Manager and
- * AppWidget Provider. Make sure StorageManagerService is completely started
- * first before continuing.
- */
- if (storageManager != null && !mOnlyCore) {
- traceBeginAndSlog("WaitForAsecScan");
- try {
- storageManager.waitForAsecScan();
- } catch (RemoteException ignored) {
- }
- traceEnd();
- }
-
traceBeginAndSlog("StartNotificationManager");
mSystemServiceManager.startService(NotificationManagerService.class);
SystemNotificationChannels.createAll(context);
@@ -1209,18 +1196,6 @@ public final class SystemServer {
traceEnd();
}
- // timezone.RulesManagerService will prevent a device starting up if the chain of trust
- // required for safe time zone updates might be broken. RuleManagerService cannot do
- // this check when mOnlyCore == true, so we don't enable the service in this case.
- final boolean startRulesManagerService =
- !mOnlyCore && context.getResources().getBoolean(
- R.bool.config_enableUpdateableTimeZoneRules);
- if (startRulesManagerService) {
- traceBeginAndSlog("StartTimeZoneRulesManagerService");
- mSystemServiceManager.startService(TIME_ZONE_RULES_MANAGER_SERVICE_CLASS);
- traceEnd();
- }
-
traceBeginAndSlog("StartAudioService");
mSystemServiceManager.startService(AudioService.Lifecycle.class);
traceEnd();
@@ -1361,6 +1336,19 @@ public final class SystemServer {
}
traceEnd();
+ // timezone.RulesManagerService will prevent a device starting up if the chain of trust
+ // required for safe time zone updates might be broken. RuleManagerService cannot do
+ // this check when mOnlyCore == true, so we don't enable the service in this case.
+ // This service requires that JobSchedulerService is already started when it starts.
+ final boolean startRulesManagerService =
+ !mOnlyCore && context.getResources().getBoolean(
+ R.bool.config_enableUpdateableTimeZoneRules);
+ if (startRulesManagerService) {
+ traceBeginAndSlog("StartTimeZoneRulesManagerService");
+ mSystemServiceManager.startService(TIME_ZONE_RULES_MANAGER_SERVICE_CLASS);
+ traceEnd();
+ }
+
if (!disableNetwork && !disableNetworkTime) {
traceBeginAndSlog("StartNetworkTimeUpdateService");
try {
@@ -1536,6 +1524,11 @@ public final class SystemServer {
traceEnd();
}
+ // Statsd helper
+ traceBeginAndSlog("StartStatsCompanionService");
+ mSystemServiceManager.startService(StatsCompanionService.Lifecycle.class);
+ traceEnd();
+
// Before things start rolling, be sure we have decided whether
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
diff --git a/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
index 58a4456ff4d7..3a92d638fb02 100644
--- a/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
@@ -30,13 +30,14 @@ import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
import com.android.internal.app.NightDisplayController;
-import com.android.internal.app.NightDisplayController.LocalTime;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.display.DisplayTransformManager;
import com.android.server.display.NightDisplayService;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -45,6 +46,7 @@ import org.mockito.Mockito;
import java.util.Calendar;
import java.util.HashMap;
+import java.time.LocalTime;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -926,11 +928,10 @@ public class NightDisplayServiceTest {
*/
private void setActivated(boolean activated, int lastActivatedTimeOffset) {
mNightDisplayController.setActivated(activated);
-
- final Calendar c = Calendar.getInstance();
- c.add(Calendar.MINUTE, lastActivatedTimeOffset);
- Secure.putLongForUser(mContext.getContentResolver(),
- Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, c.getTimeInMillis(), mUserId);
+ Secure.putStringForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
+ LocalDateTime.now().plusMinutes(lastActivatedTimeOffset).toString(),
+ mUserId);
}
/**
@@ -969,7 +970,7 @@ public class NightDisplayServiceTest {
private static LocalTime getLocalTimeRelativeToNow(int offsetMinutes) {
final Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, offsetMinutes);
- return new LocalTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
+ return LocalTime.of(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
}
/**
@@ -984,13 +985,27 @@ public class NightDisplayServiceTest {
final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset);
final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset);
- final Calendar now = Calendar.getInstance();
- long sunsetMillis = sunset.getDateTimeBefore(now).getTimeInMillis();
- long sunriseMillis = sunrise.getDateTimeBefore(now).getTimeInMillis();
+ final LocalDateTime now = LocalDateTime.now();
+ final ZoneId zoneId = ZoneId.systemDefault();
+
+ long sunsetMillis = NightDisplayService.getDateTimeBefore(sunset, now)
+ .atZone(zoneId)
+ .toInstant()
+ .toEpochMilli();
+ long sunriseMillis = NightDisplayService.getDateTimeBefore(sunrise, now)
+ .atZone(zoneId)
+ .toInstant()
+ .toEpochMilli();
if (sunsetMillis < sunriseMillis) {
- sunsetMillis = sunset.getDateTimeAfter(now).getTimeInMillis();
+ sunsetMillis = NightDisplayService.getDateTimeAfter(sunset, now)
+ .atZone(zoneId)
+ .toInstant()
+ .toEpochMilli();
} else {
- sunriseMillis = sunrise.getDateTimeAfter(now).getTimeInMillis();
+ sunriseMillis = NightDisplayService.getDateTimeAfter(sunrise, now)
+ .atZone(zoneId)
+ .toInstant()
+ .toEpochMilli();
}
return new TwilightState(sunriseMillis, sunsetMillis);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 47a3a7242a44..526f81572b07 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -20,15 +20,19 @@ import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -46,6 +50,8 @@ public class ActivityRecordTests extends ActivityTestsBase {
private final ComponentName testActivityComponent =
ComponentName.unflattenFromString("com.foo/.BarActivity");
+ private final ComponentName secondaryActivityComponent =
+ ComponentName.unflattenFromString("com.foo/.BarActivity2");
@Test
public void testStackCleanupOnClearingTask() throws Exception {
final ActivityManagerService service = createActivityManagerService();
@@ -131,4 +137,45 @@ public class ActivityRecordTests extends ActivityTestsBase {
record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */);
assertEquals(expectedActivityBounds, record.getBounds());
}
+
+
+ @Test
+ public void testCanBeLaunchedOnDisplay() throws Exception {
+ testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/,
+ true /*activityResizeable*/, true /*expected*/);
+
+ testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/,
+ false /*activityResizeable*/, false /*expected*/);
+
+ testSupportsLaunchingResizeable(true /*taskPresent*/, false /*taskResizeable*/,
+ true /*activityResizeable*/, false /*expected*/);
+
+ testSupportsLaunchingResizeable(true /*taskPresent*/, true /*taskResizeable*/,
+ false /*activityResizeable*/, true /*expected*/);
+ }
+
+ private void testSupportsLaunchingResizeable(boolean taskPresent, boolean taskResizeable,
+ boolean activityResizeable, boolean expected) {
+ final ActivityManagerService service = createActivityManagerService();
+ service.mSupportsMultiWindow = true;
+
+
+ final TaskRecord task = taskPresent
+ ? createTask(service, testActivityComponent, TEST_STACK_ID) : null;
+
+ if (task != null) {
+ task.setResizeMode(taskResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE
+ : ActivityInfo.RESIZE_MODE_UNRESIZEABLE);
+ }
+
+ final ActivityRecord record = createActivity(service, secondaryActivityComponent,
+ task);
+ record.info.resizeMode = activityResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE
+ : ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+
+ record.canBeLaunchedOnDisplay(Display.DEFAULT_DISPLAY);
+
+ assertEquals(((TestActivityStackSupervisor) service.mStackSupervisor)
+ .getLastResizeableFromCanPlaceEntityOnDisplay(), expected);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 661dd4fc828c..cd1843b37ae2 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -17,7 +17,10 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -60,7 +63,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
public void testRestoringInvalidTask() throws Exception {
final ActivityManagerService service = createActivityManagerService();
TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null);
assertNull(task);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index b5345444f8cc..0cf1df84c073 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -163,6 +163,7 @@ public class ActivityTestsBase {
*/
protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
private final ActivityDisplay mDisplay;
+ private boolean mLastResizeable;
public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
super(service, looper);
@@ -170,6 +171,22 @@ public class ActivityTestsBase {
mDisplay = new ActivityDisplay();
}
+ // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
+ // access to ActivityDisplay
+ @Override
+ boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
+ int callingUid, ActivityInfo activityInfo) {
+ mLastResizeable = resizeable;
+ return super.canPlaceEntityOnDisplay(displayId, resizeable, callingPid, callingUid,
+ activityInfo);
+ }
+
+ // TODO: remove and use Mockito verify once {@link #canPlaceEntityOnDisplay} override is
+ // removed.
+ public boolean getLastResizeableFromCanPlaceEntityOnDisplay() {
+ return mLastResizeable;
+ }
+
// No home stack is set.
@Override
void moveHomeStackToFront(String reason) {
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 4475de5aa14e..419a161669aa 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -48,13 +48,13 @@ import java.util.List;
import java.util.Set;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.android.server.am.ActivityManagerService.CONTINUE_USER_SWITCH_MSG;
-import static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG;
-import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG;
-import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG;
-import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG;
-import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG;
-import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG;
+import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
+import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
+import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
+import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
+import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG;
+import static com.android.server.am.UserController.SYSTEM_USER_START_MSG;
+import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
@@ -309,6 +309,7 @@ public class UserControllerTest extends AndroidTestCase {
private static class TestInjector extends UserController.Injector {
final Object lock = new Object();
TestHandler handler;
+ TestHandler uiHandler;
HandlerThread handlerThread;
UserManagerService userManagerMock;
UserManagerInternal userManagerInternalMock;
@@ -324,6 +325,7 @@ public class UserControllerTest extends AndroidTestCase {
handlerThread = new HandlerThread(TAG);
handlerThread.start();
handler = new TestHandler(handlerThread.getLooper());
+ uiHandler = new TestHandler(handlerThread.getLooper());
userManagerMock = mock(UserManagerService.class);
userManagerInternalMock = mock(UserManagerInternal.class);
windowManagerMock = mock(WindowManagerService.class);
@@ -337,11 +339,16 @@ public class UserControllerTest extends AndroidTestCase {
}
@Override
- protected Handler getHandler() {
+ protected Handler getHandler(Handler.Callback callback) {
return handler;
}
@Override
+ protected Handler getUiHandler(Handler.Callback callback) {
+ return uiHandler;
+ }
+
+ @Override
protected UserManagerService getUserManager() {
return userManagerMock;
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 14b1ce1662c7..4559660351b0 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -33,6 +33,10 @@ import org.junit.rules.TemporaryFolder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
+import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.eq;
@@ -83,4 +87,33 @@ public class PowerManagerServiceTest extends AndroidTestCase {
SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, "");
assertThat(reason).isEqualTo(PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN);
}
+
+ @SmallTest
+ public void testGetDesiredScreenPolicy_WithVR() throws Exception {
+ // Brighten up the screen
+ mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
+ assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+ DisplayPowerRequest.POLICY_BRIGHT);
+
+ // Move to VR
+ mService.setVrModeEnabled(true);
+ assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+ DisplayPowerRequest.POLICY_VR);
+
+ // Then take a nap
+ mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, 0);
+ assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+ DisplayPowerRequest.POLICY_OFF);
+
+ // Wake up to VR
+ mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
+ assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+ DisplayPowerRequest.POLICY_VR);
+
+ // And back to normal
+ mService.setVrModeEnabled(false);
+ assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+ DisplayPowerRequest.POLICY_BRIGHT);
+
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
index 38142d3681b6..7d73e82eaf76 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
@@ -107,7 +107,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertNotInitialized();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
@Test
@@ -119,7 +119,7 @@ public class PackageTrackerTest {
mPackageTracker.start();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
try {
// This call should also not be allowed and will throw an exception if tracking is
@@ -129,7 +129,7 @@ public class PackageTrackerTest {
} catch (IllegalStateException expected) {}
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
@Test
@@ -141,14 +141,14 @@ public class PackageTrackerTest {
mPackageTracker.start();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Receiving a check result when tracking is disabled should cause the storage to be
// reset.
mPackageTracker.recordCheckResult(null /* checkToken */, true /* success */);
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Assert the storage was reset.
checkPackageStorageStatusIsInitialOrReset();
@@ -166,13 +166,13 @@ public class PackageTrackerTest {
mPackageTracker.start();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Receiving a check result when tracking is disabled should cause the storage to be reset.
mPackageTracker.recordCheckResult(createArbitraryCheckToken(), true /* success */);
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Assert the storage was reset.
checkPackageStorageStatusIsInitialOrReset();
@@ -195,7 +195,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertNotInitialized();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
@Test
@@ -215,7 +215,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertNotInitialized();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
@Test
@@ -235,7 +235,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertNotInitialized();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
@Test
@@ -255,7 +255,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertNotInitialized();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
@Test
@@ -289,7 +289,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertUpdateNotTriggered();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Assert the storage was not touched.
checkPackageStorageStatusIsInitialOrReset();
@@ -325,7 +325,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertUpdateNotTriggered();
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Assert the storage was not touched.
checkPackageStorageStatusIsInitialOrReset();
@@ -416,7 +416,7 @@ public class PackageTrackerTest {
mPackageTracker.recordCheckResult(null /* checkToken */, success);
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Assert the storage was reset.
checkPackageStorageStatusIsInitialOrReset();
@@ -627,7 +627,7 @@ public class PackageTrackerTest {
mPackageTracker.recordCheckResult(token1, true /* success */);
// Reliability triggering should still be enabled.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Check the expected storage state.
checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions2);
@@ -743,7 +743,7 @@ public class PackageTrackerTest {
// Under the covers we expect it to fail to update because the storage should recognize that
// the token is no longer valid.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Peek inside the package tracker to make sure it is tracking failure counts properly.
assertEquals(1, mPackageTracker.getCheckFailureCountForTests());
@@ -766,7 +766,7 @@ public class PackageTrackerTest {
checkPackageStorageStatusIsInitialOrReset();
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did trigger an update.
checkUpdateCheckTriggered(packageVersions);
@@ -803,7 +803,7 @@ public class PackageTrackerTest {
checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did not attempt to trigger an update.
mFakeIntentHelper.assertUpdateNotTriggered();
@@ -843,7 +843,7 @@ public class PackageTrackerTest {
checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did trigger an update.
checkUpdateCheckTriggered(currentPackageVersions);
@@ -890,7 +890,7 @@ public class PackageTrackerTest {
for (int i = 0; i < retriesAllowed + 1; i++) {
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did trigger an update.
checkUpdateCheckTriggered(currentPackageVersions);
@@ -912,9 +912,9 @@ public class PackageTrackerTest {
// Check reliability triggering is in the correct state.
if (i <= retriesAllowed) {
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
} else {
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
}
}
}
@@ -950,7 +950,7 @@ public class PackageTrackerTest {
// Fail (retries - 1) times.
for (int i = 0; i < retriesAllowed - 1; i++) {
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did trigger an update.
checkUpdateCheckTriggered(currentPackageVersions);
@@ -971,11 +971,11 @@ public class PackageTrackerTest {
currentPackageVersions);
// Check reliability triggering is still enabled.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
}
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did trigger an update.
checkUpdateCheckTriggered(currentPackageVersions);
@@ -1023,7 +1023,7 @@ public class PackageTrackerTest {
checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did trigger an update.
checkUpdateCheckTriggered(currentPackageVersions);
@@ -1033,18 +1033,18 @@ public class PackageTrackerTest {
mFakeClock.incrementClock(checkDelayMillis - 1);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did not trigger an update.
mFakeIntentHelper.assertUpdateNotTriggered();
checkPackageStorageStatus(PackageStatus.CHECK_STARTED, currentPackageVersions);
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Increment the clock slightly more. Should now consider the response overdue.
mFakeClock.incrementClock(2);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Triggering should have happened.
checkUpdateCheckTriggered(currentPackageVersions);
@@ -1096,7 +1096,7 @@ public class PackageTrackerTest {
mFakeClock.incrementClock(checkDelayMillis + 1);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker triggered an update.
checkUpdateCheckTriggered(newPackageVersions);
@@ -1154,18 +1154,18 @@ public class PackageTrackerTest {
mFakeClock.incrementClock(checkDelayMillis - 1);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Assert the PackageTracker did not trigger an update.
mFakeIntentHelper.assertUpdateNotTriggered();
checkPackageStorageStatus(PackageStatus.CHECK_STARTED, newPackageVersions);
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Increment the clock slightly more. Should now consider the response overdue.
mFakeClock.incrementClock(2);
// Simulate a reliability trigger.
- mFakeIntentHelper.simulateReliabilityTrigger();
+ mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
// Triggering should have happened.
checkUpdateCheckTriggered(newPackageVersions);
@@ -1202,7 +1202,7 @@ public class PackageTrackerTest {
// If an update check was triggered reliability triggering should always be enabled to
// ensure that it can be completed if it fails.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Check the expected storage state.
checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions);
@@ -1210,7 +1210,7 @@ public class PackageTrackerTest {
private void checkUpdateCheckFailed(PackageVersions packageVersions) {
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
// Assert the storage was updated.
checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions);
@@ -1218,7 +1218,7 @@ public class PackageTrackerTest {
private void checkUpdateCheckSuccessful(PackageVersions packageVersions) {
// Check reliability triggering state.
- mFakeIntentHelper.assertReliabilityTriggeringDisabled();
+ mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
// Assert the storage was updated.
checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
@@ -1345,7 +1345,7 @@ public class PackageTrackerTest {
mFakeIntentHelper.assertInitialized(UPDATE_APP_PACKAGE_NAME, DATA_APP_PACKAGE_NAME);
// Assert that reliability tracking is always enabled after initialization.
- mFakeIntentHelper.assertReliabilityTriggeringEnabled();
+ mFakeIntentHelper.assertReliabilityTriggerScheduled();
}
private void checkPackageStorageStatus(
@@ -1368,34 +1368,34 @@ public class PackageTrackerTest {
*/
private static class FakeIntentHelper implements IntentHelper {
- private Listener mListener;
+ private PackageTracker mPackageTracker;
private String mUpdateAppPackageName;
private String mDataAppPackageName;
private CheckToken mLastToken;
- private boolean mReliabilityTriggeringEnabled;
+ private boolean mReliabilityTriggerScheduled;
@Override
public void initialize(String updateAppPackageName, String dataAppPackageName,
- Listener listener) {
+ PackageTracker packageTracker) {
assertNotNull(updateAppPackageName);
assertNotNull(dataAppPackageName);
- assertNotNull(listener);
- mListener = listener;
+ assertNotNull(packageTracker);
+ mPackageTracker = packageTracker;
mUpdateAppPackageName = updateAppPackageName;
mDataAppPackageName = dataAppPackageName;
}
public void assertInitialized(
String expectedUpdateAppPackageName, String expectedDataAppPackageName) {
- assertNotNull(mListener);
+ assertNotNull(mPackageTracker);
assertEquals(expectedUpdateAppPackageName, mUpdateAppPackageName);
assertEquals(expectedDataAppPackageName, mDataAppPackageName);
}
public void assertNotInitialized() {
- assertNull(mListener);
+ assertNull(mPackageTracker);
}
@Override
@@ -1407,21 +1407,21 @@ public class PackageTrackerTest {
}
@Override
- public void enableReliabilityTriggering() {
- mReliabilityTriggeringEnabled = true;
+ public void scheduleReliabilityTrigger(long minimumDelayMillis) {
+ mReliabilityTriggerScheduled = true;
}
@Override
- public void disableReliabilityTriggering() {
- mReliabilityTriggeringEnabled = false;
+ public void unscheduleReliabilityTrigger() {
+ mReliabilityTriggerScheduled = false;
}
- public void assertReliabilityTriggeringEnabled() {
- assertTrue(mReliabilityTriggeringEnabled);
+ public void assertReliabilityTriggerScheduled() {
+ assertTrue(mReliabilityTriggerScheduled);
}
- public void assertReliabilityTriggeringDisabled() {
- assertFalse(mReliabilityTriggeringEnabled);
+ public void assertReliabilityTriggerNotScheduled() {
+ assertFalse(mReliabilityTriggerScheduled);
}
public void assertUpdateTriggered() {
@@ -1440,11 +1440,7 @@ public class PackageTrackerTest {
}
public void simulatePackageUpdatedEvent() {
- mListener.triggerUpdateIfNeeded(true);
- }
-
- public void simulateReliabilityTrigger() {
- mListener.triggerUpdateIfNeeded(false);
+ mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index e39cccab7bad..5d2bb4d92620 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -102,7 +102,7 @@ public class WindowFrameTests extends WindowTestsBase {
sWm.mSystemDecorLayer = 10000;
mWindowToken = new WindowTestUtils.TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
- mStubStack = new TaskStack(sWm, 0);
+ mStubStack = new TaskStack(sWm, 0, null);
}
public void assertRect(Rect rect, int left, int top, int right, int bottom) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 2ae10aadb10c..0315c8d6f9ba 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -78,7 +78,7 @@ public class WindowTestUtils {
*/
public static class TestTaskStack extends TaskStack {
TestTaskStack(WindowManagerService service, int stackId) {
- super(service, stackId);
+ super(service, stackId, null);
}
@Override
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 3788cf331600..b040a6324dbb 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.START_ASSISTANT_HIDDEN_SESSION;
import static android.app.ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION;
import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
@@ -222,8 +223,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
intent = new Intent(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(StackId.ASSISTANT_STACK_ID);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchActivityType(ACTIVITY_TYPE_ASSISTANT);
return mAm.startAssistantActivity(mComponent.getPackageName(), callingPid, callingUid,
intent, resolvedType, options.toBundle(), mUser);
} catch (RemoteException e) {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index d5ff1adb607d..ff6711632252 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -77,9 +77,28 @@ public class PhoneNumberUtils
public static final int TOA_International = 0x91;
public static final int TOA_Unknown = 0x81;
+ /*
+ * The BCD extended type used to determine the extended char for the digit which is greater than
+ * 9.
+ *
+ * see TS 51.011 section 10.5.1 EF_ADN(Abbreviated dialling numbers)
+ */
+ public static final int BCD_EXTENDED_TYPE_EF_ADN = 1;
+
+ /*
+ * The BCD extended type used to determine the extended char for the digit which is greater than
+ * 9.
+ *
+ * see TS 24.008 section 10.5.4.7 Called party BCD number
+ */
+ public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2;
+
static final String LOG_TAG = "PhoneNumberUtils";
private static final boolean DBG = false;
+ private static final String BCD_EF_ADN_EXTENDED = "*#,N;";
+ private static final String BCD_CALLED_PARTY_EXTENDED = "*#abc";
+
/*
* global-phone-number = ["+"] 1*( DIGIT / written-sep )
* written-sep = ("-"/".")
@@ -799,11 +818,33 @@ public class PhoneNumberUtils
*
* @return partial string on invalid decode
*
- * FIXME(mkf) support alphanumeric address type
- * currently implemented in SMSMessage.getAddress()
+ * @deprecated use {@link #calledPartyBCDToString(byte[], int, int, int)} instead. Calling this
+ * method is equivalent to calling {@link #calledPartyBCDToString(byte[], int, int)} with
+ * {@link #BCD_EXTENDED_TYPE_EF_ADN} as the extended type.
*/
- public static String
- calledPartyBCDToString (byte[] bytes, int offset, int length) {
+ @Deprecated
+ public static String calledPartyBCDToString(byte[] bytes, int offset, int length) {
+ return calledPartyBCDToString(bytes, offset, length, BCD_EXTENDED_TYPE_EF_ADN);
+ }
+
+ /**
+ * 3GPP TS 24.008 10.5.4.7
+ * Called Party BCD Number
+ *
+ * See Also TS 51.011 10.5.1 "dialing number/ssc string"
+ * and TS 11.11 "10.3.1 EF adn (Abbreviated dialing numbers)"
+ *
+ * @param bytes the data buffer
+ * @param offset should point to the TOA (aka. TON/NPI) octet after the length byte
+ * @param length is the number of bytes including TOA byte
+ * and must be at least 2
+ * @param bcdExtType used to determine the extended bcd coding
+ * @see #BCD_EXTENDED_TYPE_EF_ADN
+ * @see #BCD_EXTENDED_TYPE_CALLED_PARTY
+ *
+ */
+ public static String calledPartyBCDToString(
+ byte[] bytes, int offset, int length, int bcdExtType) {
boolean prependPlus = false;
StringBuilder ret = new StringBuilder(1 + length * 2);
@@ -817,7 +858,7 @@ public class PhoneNumberUtils
}
internalCalledPartyBCDFragmentToString(
- ret, bytes, offset + 1, length - 1);
+ ret, bytes, offset + 1, length - 1, bcdExtType);
if (prependPlus && ret.length() == 0) {
// If the only thing there is a prepended plus, return ""
@@ -902,14 +943,13 @@ public class PhoneNumberUtils
return ret.toString();
}
- private static void
- internalCalledPartyBCDFragmentToString(
- StringBuilder sb, byte [] bytes, int offset, int length) {
+ private static void internalCalledPartyBCDFragmentToString(
+ StringBuilder sb, byte [] bytes, int offset, int length, int bcdExtType) {
for (int i = offset ; i < length + offset ; i++) {
byte b;
char c;
- c = bcdToChar((byte)(bytes[i] & 0xf));
+ c = bcdToChar((byte)(bytes[i] & 0xf), bcdExtType);
if (c == 0) {
return;
@@ -930,7 +970,7 @@ public class PhoneNumberUtils
break;
}
- c = bcdToChar(b);
+ c = bcdToChar(b, bcdExtType);
if (c == 0) {
return;
}
@@ -943,49 +983,65 @@ public class PhoneNumberUtils
/**
* Like calledPartyBCDToString, but field does not start with a
* TOA byte. For example: SIM ADN extension fields
+ *
+ * @deprecated use {@link #calledPartyBCDFragmentToString(byte[], int, int, int)} instead.
+ * Calling this method is equivalent to calling
+ * {@link #calledPartyBCDFragmentToString(byte[], int, int, int)} with
+ * {@link #BCD_EXTENDED_TYPE_EF_ADN} as the extended type.
*/
+ @Deprecated
+ public static String calledPartyBCDFragmentToString(byte[] bytes, int offset, int length) {
+ return calledPartyBCDFragmentToString(bytes, offset, length, BCD_EXTENDED_TYPE_EF_ADN);
+ }
- public static String
- calledPartyBCDFragmentToString(byte [] bytes, int offset, int length) {
+ /**
+ * Like calledPartyBCDToString, but field does not start with a
+ * TOA byte. For example: SIM ADN extension fields
+ */
+ public static String calledPartyBCDFragmentToString(
+ byte[] bytes, int offset, int length, int bcdExtType) {
StringBuilder ret = new StringBuilder(length * 2);
-
- internalCalledPartyBCDFragmentToString(ret, bytes, offset, length);
-
+ internalCalledPartyBCDFragmentToString(ret, bytes, offset, length, bcdExtType);
return ret.toString();
}
- /** returns 0 on invalid value */
- private static char
- bcdToChar(byte b) {
+ /**
+ * Returns the correspond character for given {@code b} based on {@code bcdExtType}, or 0 on
+ * invalid code.
+ */
+ private static char bcdToChar(byte b, int bcdExtType) {
if (b < 0xa) {
- return (char)('0' + b);
- } else switch (b) {
- case 0xa: return '*';
- case 0xb: return '#';
- case 0xc: return PAUSE;
- case 0xd: return WILD;
+ return (char) ('0' + b);
+ }
- default: return 0;
+ String extended = null;
+ if (BCD_EXTENDED_TYPE_EF_ADN == bcdExtType) {
+ extended = BCD_EF_ADN_EXTENDED;
+ } else if (BCD_EXTENDED_TYPE_CALLED_PARTY == bcdExtType) {
+ extended = BCD_CALLED_PARTY_EXTENDED;
}
+ if (extended == null || b - 0xa >= extended.length()) {
+ return 0;
+ }
+
+ return extended.charAt(b - 0xa);
}
- private static int
- charToBCD(char c) {
- if (c >= '0' && c <= '9') {
+ private static int charToBCD(char c, int bcdExtType) {
+ if ('0' <= c && c <= '9') {
return c - '0';
- } else if (c == '*') {
- return 0xa;
- } else if (c == '#') {
- return 0xb;
- } else if (c == PAUSE) {
- return 0xc;
- } else if (c == WILD) {
- return 0xd;
- } else if (c == WAIT) {
- return 0xe;
- } else {
- throw new RuntimeException ("invalid char for BCD " + c);
}
+
+ String extended = null;
+ if (BCD_EXTENDED_TYPE_EF_ADN == bcdExtType) {
+ extended = BCD_EF_ADN_EXTENDED;
+ } else if (BCD_EXTENDED_TYPE_CALLED_PARTY == bcdExtType) {
+ extended = BCD_CALLED_PARTY_EXTENDED;
+ }
+ if (extended == null || extended.indexOf(c) == -1) {
+ throw new RuntimeException("invalid char for BCD " + c);
+ }
+ return 0xa + extended.indexOf(c);
}
/**
@@ -1034,40 +1090,60 @@ public class PhoneNumberUtils
*
* Returns null if network portion is empty.
*/
- public static byte[]
- networkPortionToCalledPartyBCD(String s) {
+ public static byte[] networkPortionToCalledPartyBCD(String s) {
String networkPortion = extractNetworkPortion(s);
- return numberToCalledPartyBCDHelper(networkPortion, false);
+ return numberToCalledPartyBCDHelper(
+ networkPortion, false, BCD_EXTENDED_TYPE_EF_ADN);
}
/**
* Same as {@link #networkPortionToCalledPartyBCD}, but includes a
* one-byte length prefix.
*/
- public static byte[]
- networkPortionToCalledPartyBCDWithLength(String s) {
+ public static byte[] networkPortionToCalledPartyBCDWithLength(String s) {
String networkPortion = extractNetworkPortion(s);
- return numberToCalledPartyBCDHelper(networkPortion, true);
+ return numberToCalledPartyBCDHelper(
+ networkPortion, true, BCD_EXTENDED_TYPE_EF_ADN);
+ }
+
+ /**
+ * Convert a dialing number to BCD byte array
+ *
+ * @param number dialing number string. If the dialing number starts with '+', set to
+ * international TOA
+ *
+ * @return BCD byte array
+ *
+ * @deprecated use {@link #numberToCalledPartyBCD(String, int)} instead. Calling this method
+ * is equivalent to calling {@link #numberToCalledPartyBCD(String, int)} with
+ * {@link #BCD_EXTENDED_TYPE_EF_ADN} as the extended type.
+ */
+ @Deprecated
+ public static byte[] numberToCalledPartyBCD(String number) {
+ return numberToCalledPartyBCD(number, BCD_EXTENDED_TYPE_EF_ADN);
}
/**
* Convert a dialing number to BCD byte array
*
- * @param number dialing number string
- * if the dialing number starts with '+', set to international TOA
+ * @param number dialing number string. If the dialing number starts with '+', set to
+ * international TOA
+ * @param bcdExtType used to determine the extended bcd coding
+ * @see #BCD_EXTENDED_TYPE_EF_ADN
+ * @see #BCD_EXTENDED_TYPE_CALLED_PARTY
+ *
* @return BCD byte array
*/
- public static byte[]
- numberToCalledPartyBCD(String number) {
- return numberToCalledPartyBCDHelper(number, false);
+ public static byte[] numberToCalledPartyBCD(String number, int bcdExtType) {
+ return numberToCalledPartyBCDHelper(number, false, bcdExtType);
}
/**
* If includeLength is true, prepend a one-byte length value to
* the return array.
*/
- private static byte[]
- numberToCalledPartyBCDHelper(String number, boolean includeLength) {
+ private static byte[] numberToCalledPartyBCDHelper(
+ String number, boolean includeLength, int bcdExtType) {
int numberLenReal = number.length();
int numberLenEffective = numberLenReal;
boolean hasPlus = number.indexOf('+') != -1;
@@ -1087,7 +1163,8 @@ public class PhoneNumberUtils
char c = number.charAt(i);
if (c == '+') continue;
int shift = ((digitCount & 0x01) == 1) ? 4 : 0;
- result[extraBytes + (digitCount >> 1)] |= (byte)((charToBCD(c) & 0x0F) << shift);
+ result[extraBytes + (digitCount >> 1)] |=
+ (byte)((charToBCD(c, bcdExtType) & 0x0F) << shift);
digitCount++;
}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 36abfc9d288e..489c208a0d46 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -19,7 +19,9 @@ package com.android.ims;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import android.telecom.VideoProfile;
+import android.util.Log;
import com.android.internal.telephony.PhoneConstants;
@@ -216,6 +218,29 @@ public class ImsCallProfile implements Parcelable {
public int mServiceType;
public int mCallType;
public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
+
+ /**
+ * Extras associated with this {@link ImsCallProfile}.
+ * <p>
+ * Valid data types include:
+ * <ul>
+ * <li>{@link Integer} (and int)</li>
+ * <li>{@link Long} (and long)</li>
+ * <li>{@link Double} (and double)</li>
+ * <li>{@link String}</li>
+ * <li>{@code int[]}</li>
+ * <li>{@code long[]}</li>
+ * <li>{@code double[]}</li>
+ * <li>{@code String[]}</li>
+ * <li>{@link PersistableBundle}</li>
+ * <li>{@link Boolean} (and boolean)</li>
+ * <li>{@code boolean[]}</li>
+ * <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li>
+ * </ul>
+ * <p>
+ * Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across
+ * a {@link android.os.Binder}.
+ */
public Bundle mCallExtras;
public ImsStreamMediaProfile mMediaProfile;
@@ -315,16 +340,17 @@ public class ImsCallProfile implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
+ Bundle filteredExtras = maybeCleanseExtras(mCallExtras);
out.writeInt(mServiceType);
out.writeInt(mCallType);
- out.writeParcelable(mCallExtras, 0);
+ out.writeBundle(filteredExtras);
out.writeParcelable(mMediaProfile, 0);
}
private void readFromParcel(Parcel in) {
mServiceType = in.readInt();
mCallType = in.readInt();
- mCallExtras = in.readParcelable(null);
+ mCallExtras = in.readBundle();
mMediaProfile = in.readParcelable(null);
}
@@ -465,6 +491,31 @@ public class ImsCallProfile implements Parcelable {
}
/**
+ * Cleanses a {@link Bundle} to ensure that it contains only data of type:
+ * 1. Primitive data types (e.g. int, bool, and other values determined by
+ * {@link android.os.PersistableBundle#isValidType(Object)}).
+ * 2. Other Bundles.
+ * 3. {@link Parcelable} objects in the {@code android.*} namespace.
+ * @param extras the source {@link Bundle}
+ * @return where all elements are valid types the source {@link Bundle} is returned unmodified,
+ * otherwise a copy of the {@link Bundle} with the invalid elements is returned.
+ */
+ private Bundle maybeCleanseExtras(Bundle extras) {
+ if (extras == null) {
+ return null;
+ }
+
+ int startSize = extras.size();
+ Bundle filtered = extras.filterValues();
+ int endSize = filtered.size();
+ if (startSize != endSize) {
+ Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were "
+ + "removed - only primitive types and system parcelables are permitted.");
+ }
+ return filtered;
+ }
+
+ /**
* Determines if a video state is set in a video state bit-mask.
*
* @param videoState The video state bit mask.
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 629173dfa23b..7a53ef63e2a8 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -161,7 +161,7 @@ public class SmsMessage extends SmsMessageBase {
// Second byte is the MSG_LEN, length of the message
// See 3GPP2 C.S0023 3.4.27
- int size = data[1];
+ int size = data[1] & 0xFF;
// Note: Data may include trailing FF's. That's OK; message
// should still parse correctly.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
index 2fbf7ed5648c..bd8c83e63055 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.gsm;
import android.telephony.PhoneNumberUtils;
+
import java.text.ParseException;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.SmsAddress;
@@ -71,8 +72,11 @@ public class GsmSmsAddress extends SmsAddress {
// Make sure the final unused BCD digit is 0xf
origBytes[length - 1] |= 0xf0;
}
- address = PhoneNumberUtils.calledPartyBCDToString(origBytes,
- OFFSET_TOA, length - OFFSET_TOA);
+ address = PhoneNumberUtils.calledPartyBCDToString(
+ origBytes,
+ OFFSET_TOA,
+ length - OFFSET_TOA,
+ PhoneNumberUtils.BCD_EXTENDED_TYPE_CALLED_PARTY);
// And restore origBytes
origBytes[length - 1] = lastByte;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index d4098d94ba6c..1ca19e01d6c8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -535,8 +535,8 @@ public class SmsMessage extends SmsMessageBase {
} else {
// SC address
try {
- ret = PhoneNumberUtils
- .calledPartyBCDToString(mPdu, mCur, len);
+ ret = PhoneNumberUtils.calledPartyBCDToString(
+ mPdu, mCur, len, PhoneNumberUtils.BCD_EXTENDED_TYPE_CALLED_PARTY);
} catch (RuntimeException tr) {
Rlog.d(LOG_TAG, "invalid SC address: ", tr);
ret = null;
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index f72a1c638ed5..262417620ca2 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -512,7 +512,7 @@ public class IpConnectivityEventBuilderTest {
stats.nonApplicationWakeups = 1;
stats.rootWakeups = 2;
stats.systemWakeups = 3;
- stats.unroutedWakeups = 3;
+ stats.noUidWakeups = 3;
IpConnectivityEvent got = IpConnectivityEventBuilder.toProto(stats);
String want = String.join("\n",
@@ -526,11 +526,11 @@ public class IpConnectivityEventBuilderTest {
" wakeup_stats <",
" application_wakeups: 5",
" duration_sec: 0",
+ " no_uid_wakeups: 3",
" non_application_wakeups: 1",
" root_wakeups: 2",
" system_wakeups: 3",
" total_wakeups: 14",
- " unrouted_wakeups: 3",
" >",
">",
"version: 2\n");
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index ede5988cdc6d..a395c480f57a 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -423,11 +423,11 @@ public class IpConnectivityMetricsTest {
" wakeup_stats <",
" application_wakeups: 2",
" duration_sec: 0",
+ " no_uid_wakeups: 0",
" non_application_wakeups: 0",
" root_wakeups: 0",
" system_wakeups: 1",
" total_wakeups: 3",
- " unrouted_wakeups: 0",
" >",
">",
"events <",
@@ -439,11 +439,11 @@ public class IpConnectivityMetricsTest {
" wakeup_stats <",
" application_wakeups: 1",
" duration_sec: 0",
+ " no_uid_wakeups: 1",
" non_application_wakeups: 0",
" root_wakeups: 0",
" system_wakeups: 2",
" total_wakeups: 4",
- " unrouted_wakeups: 1",
" >",
">",
"version: 2\n");
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 2b105e5c92ee..6723601fc5c3 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -163,11 +163,11 @@ public class NetdEventListenerServiceTest {
" wakeup_stats <",
" application_wakeups: 3",
" duration_sec: 0",
+ " no_uid_wakeups: 0",
" non_application_wakeups: 0",
" root_wakeups: 0",
" system_wakeups: 2",
" total_wakeups: 5",
- " unrouted_wakeups: 0",
" >",
">",
"events <",
@@ -179,11 +179,11 @@ public class NetdEventListenerServiceTest {
" wakeup_stats <",
" application_wakeups: 2",
" duration_sec: 0",
+ " no_uid_wakeups: 2",
" non_application_wakeups: 1",
" root_wakeups: 2",
" system_wakeups: 3",
" total_wakeups: 10",
- " unrouted_wakeups: 2",
" >",
">",
"version: 2\n");